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; } }