Linked list must brush questions: speed double pointer, linked list reverse, find the midpoint template·····

Posted by luisantonio on Mon, 13 Dec 2021 15:36:32 +0100

234. Palindrome linked list

Very representative! It includes linked list traversal, fast and slow pointer, midpoint template, linked list data comparison and linked list inversion! Very representative

class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null) return true;
        // Find the midpoint 1 = > 1 123 = > 2 1234 = > 2
        ListNode A_end = mid(head);
        ListNode B_start = A_end.next;
        A_end.next = null;
        // Flip back half
        B_start = reverse(B_start);
        // comparison
        boolean res = compare(head, B_start);
        // reduction
        A_end.next = reverse(B_start);
        return res;
    }
    // Linked list to find the midpoint, fast and slow pointer method
    ListNode mid(ListNode head) {
        ListNode p = head;
        ListNode q = head;
        while(q.next != null && q.next.next != null) {
            p = p.next;
            q = q.next.next;
        }
        return p;
    }
    // Linked list inversion template
    ListNode reverse(ListNode head) { // Three person line template
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null) {
            ListNode temp = cur.next; // Let go and save
            cur.next = pre;
            pre = cur; // Homing
            cur = temp;
        }
        return pre;
    }
    // Linked list comparison template (len (b) < = len (a))
    boolean compare(ListNode A, ListNode B) {
        while(B != null) {
            if(A.val != B.val) return false;
            A = A.next;
            B = B.next;
        }
        return true;
    }
}

23. Merge K ascending linked lists

Difficulty difficulty

Merging two linked lists is not difficult to create a virtual head node from a small to a connection node! The key lies in how to find the summary points and compare them one by one. However, multiple linked lists have to sort each training table to find the summary points. At this time, a sorting queue PriorityQueue is required

PriorityQueue<ListNode> pd = new Priority<>(length,(a,b)->(a.val - b.val))
    The first parameter is the queue length, and the second is the collation: logarithm

So the answer is as follows:

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0){
            return null;
        }
        //The linked list is stored in a sort queue
            // Priority queue, minimum heap
       PriorityQueue<ListNode> pq = new PriorityQueue<>(
        lists.length, (a, b)->(a.val - b.val));
        //PriorityQueue pq = new PriorityQueue<>(lists.length,(a,b)->(a.val - b.val));
        for(ListNode list : lists){
            if(list != null){
                 pq.add(list);
            }  
        }
        //Set a virtual node
        ListNode dummy = new ListNode();
        //The head node cannot be moved
        ListNode p = dummy;
        while(!pq.isEmpty()){
            ListNode temp = pq.poll();
            p.next = temp;
            if(temp.next != null){
                pq.add(temp.next);
            }
            p = p.next;
        }
        return dummy.next;
    }
}

141. Circular linked list

Judge whether the linked list has a ring. The fast and slow double pointers. One takes two steps, and the other will always meet. When meeting, the fast pointer will take one more ring distance than the slow needle,

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        //Note that this is & & and both conditions have to be met
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                return true;
            }
        }
        return false;
    }
}

So how to find the first node of intersection? After finding the same node, let the slow needle return to the head node, and the fast pointer stop in place. The two take one step at the same time. The point where they meet for the first time is the ring entry node;

 //Note that this is & & and both conditions have to be met
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                //Find ring node here
                //Slow the pointer back to the borrowing point
                slow = head;
                //Take one step at the same time
                while(slow != fast){
					slow = slow.next;
                    fast = fast.next;
                }
                //Then there is the head borrowing position!
                return slow;
            }
        }

19. Delete the penultimate node of the linked list

The key is how to find the penultimate node! Use the speed pointer to take n steps first, and then take one step at the same time! The last position reached by the slow pointer is the penultimate node
Just delete it
But: what if the first node is deleted?
This requires adding a virtual head node!

 /*
 The key is how to find the penultimate node! Use the speed pointer to take n steps first, and then take one step at the same time! The last position reached by the slow pointer is the penultimate node
 Just delete it
 But: what if the first node is deleted?
 This requires adding a virtual head node!
  */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
            //Find this node, speed pointer
            ListNode fast = new ListNode(0,head);
            ListNode slow = new ListNode(0,head);
            ListNode dummy = slow;
            while(n > 0){
                fast = fast.next;
                n--;
            }
            while(fast.next != null){
                fast = fast.next;
                slow = slow.next;
            }
            slow.next = slow.next.next;
            return dummy.next;
    }
}

92. Reverse linked list II

Classic in classic! Reversing the entire linked list is very simple!

ListNode reverse(ListNode head){
    if(head.next == null){
        return head;
    }
    ListNode last = reverse(head.next);
    head.next.next = head;
    head.next = null;
    return last;
}
  • Reversing the first n is also simple! Just change the basecase without going to the end
ListNode reverse(ListNode head,int n){
    if(n == 1){
        //You need to record the rear drive node
        houqu = head.next;
        return head;
    }
    ListNode last = reverse(head.next,n-1);
    head.next.next = head;
    head.next = houqu;
    return last;
}
  • So here's the point! What about reversing a part of the linked list?
  • Learn how to convert what won't be into what will be. We will reverse the first N and convert it into the first n. that is, use recursion to change the starting position on the left to 1,
ListNode reverseBetwen(ListNode head, int left, int right){
    if(left == 1){
        //reversal
        return reverse(head, right);
    }
    //Pick it up
    head.next = reverseBetwen(head.next,left - 1, right -1);
    return head;
}

25. Turn over the linked list in groups of K

Reversing the first k is very simple and requires recording the back drive nodes, but there are not only the first k, but multiple first k;
Two nodes are required to record the starting point and ending point of the linked list to be reversed, a and B
Take a as the starting point and reverse [a,b) the linked list!
Recursion starting from B as another group will generate another [a,b)
Connect the first a to the second inverted node!

 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if (head == null) return null;
        ListNode a = head,b = head;
        //Determine whether it is enough to reverse
        for(int i = 0; i < k; i++){
            if(b == null){
                return head;
            }
            b = b.next;
        }
        //Enough to reverse [a,b)
        ListNode newNode = reverseK(a,b);
        //Connection node
        a.next = reverseKGroup(b,k);
        return newNode;
    }
    //Invert interval node
    ListNode reverseK(ListNode a, ListNode b){
        if(a.next == b){
            return a;
        }
        ListNode last = reverseK(a.next, b);
        a.next.next = a;
        a.next = null;
        return last;
    }
}

Topics: Algorithm data structure leetcode linked list