Leetcode Brush Title Notes - Basic Operation and Classic Title of Chain List

Posted by qrt123 on Sat, 22 Jan 2022 21:35:16 +0100

Brush the title from: Code Casual Recording

1. Chain list basic operations

707. Design Chain List

Leetcode Link

Design the implementation of the chain table. You can choose to use single or double-linked lists. A node in a single-chain table should have two attributes: val and next. val is the value of the current node, and next is the pointer/reference to the next node. If you want to use a two-way Chain table, you also need an attribute prev to indicate the last node in the chain table. Assume that all nodes in the chain table are 0-index.

Implement these functions in a linked list class:

get(index): Gets the value of the index node in the chain table. Returns -1 if the index is invalid.
addAtHead(val): Head insert
addAtTail(val): End Interpolation
addAtIndex(index,val): A node whose value is Val is added before the index node in the chain table. If index equals the length of the list, the node is appended to the end of the list. If the index is larger than the length of the list, no node will be inserted. If index is less than 0, the node is inserted in the header.
DeleteAtIndex: Deletes the index node in the chain table.

Example:
MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); // Chain list becomes 1-> 2-> 3
linkedList.get(1); // Return 2
linkedList.deleteAtIndex(1); // Now the list is 1-> 3
linkedList.get(1); // Return 3

Questions:

class Node {
	int val;
	Node next;
	public Node(int val) {
		this.val = val;
	}
}
class MyLinkedList {
	Node head = null;
	int size = 0;
    public MyLinkedList() {
    }
    
    // Gets the value of the index node in the chain table. Returns -1 if the index is invalid.
    public int get(int index) {
    	if (index + 1 > size || index < 0) return -1;
    	Node cur = this.head;
    	for (int i = 0; i < index; i ++) {
    		cur = cur.next;
    	}
		return cur.val;
    }
    
    // Head plug
    public void addAtHead(int val) {
    	Node node = new Node(val);
    	if (this.head == null) {
    		this.head = node;
    	} else {
			node.next = this.head;
			this.head = node;
		}
		size++;
    }
    
    // Tail insertion
    public void addAtTail(int val) {
    	Node node = new Node(val);
    	if (this.head == null) {
    		this.head = node;
    	} else {
    		Node cur = this.head;
    		while (cur.next != null) {
    			cur = cur.next;
    		}
    		cur.next = node;
    	}
    	size++;
    }
    
    // Add a node with val ue before index nodes.
    public void addAtIndex(int index, int val) {
    	// index is larger than the length of the list, nodes are not inserted
    	if (index > size) return;
    	// If index is less than or equal to 0, a node is inserted in the head.
    	if (index <= 0) {
    		addAtHead(val);
    		return;
    	}
    	// If index equals the length of the list, the node is appended to the end of the list.
    	if (index == size) {
    		addAtTail(val);
    		return;
    	}
    	// Insert in the middle
        Node node = new Node(val);
    	Node prev = head;
    	// prev finds the previous node to insert
    	for (int i = 0; i < index - 1; i ++) {
    		prev = prev.next;
    	}
    	node.next = prev.next;
    	prev.next = node;
    	size++;
    }
    
    // Delete the index node in the list.
    public void deleteAtIndex(int index) {
		if (index > size - 1 || index < 0) return;
		if (index == 0) {
			this.head = this.head.next;
			size--;
			return;
		}
		if (index == size- 1) {
			Node prev = this.head;
			for (int i = 0; i < index- 1; i ++) {
				prev = prev.next;
			}
			prev.next = null;
			size--;
			return;
		}
		
		Node prev = head;
		for (int i = 0; i < index - 1; i ++) {
			prev = prev.next;
		}
		prev.next = prev.next.next;
		size--;
    }
}

2. Double Pointer Iteration

203. Remove Chain List Elements

Leetcode Link
Give you a header node of the list and an integer val. Delete all Nodes in the list. Val == Val node and returns a new header node.

Example 1:
Input: head = [1,2,6,3,4,5,6], val = 6
Output: [1,2,3,4,5]

Example 2:
Input: head = [], val = 1
Output: []

Example 3:
Input: head = [7,7,7,7], val = 7
Output: []

Questions:
Method 1:

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) return head;
        ListNode prev = head;
        ListNode cur = prev.next;
        while (cur != null) {
            if (cur.val == val) {
            	// delete
                prev.next = cur.next;
                cur = prev.next; 
            } else {
            	// Do not delete
                prev = cur;
                cur = prev.next;
            }
        }
        // Because cur is looking backwards from the second node, the head node has not yet determined whether to delete the node
        if (head.val == val) {
            return head.next;
        } else {
            return head;
        }
    }
}

Method 2: Add virtual header node

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) return head;
        // Virtual Header Node
        ListNode newHead = new ListNode(-1);
        newHead.next = head;
        ListNode prev = newHead;
        ListNode cur = prev.next;
        // iteration
        while (cur != null) {
            if (cur.val == val) {
                prev.next = cur.next;
            } else {
                prev = cur;
            }
            // Can be placed outside judgment
            cur = prev.next;
        }
        return newHead.next;
    }
}

206. Inverse Chain List

Leetcode Link
Defines a function that inputs the head node of a chain table, inverts the chain table, and outputs the head node of the chain table after inversion.

Example:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL

Questions:
Notice the initial value and the end of iteration condition

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null) return null;
        // The original header node should point to null after inversion
        ListNode prev = null;
        ListNode cur = head;
        // If the curNext initial value is cur.next, the pointer crosses the boundary at the end
        ListNode curNext = cur;
        while (cur != null) {
        	// Point curNext at the beginning of each iteration. Next
            curNext = cur.next;
            // Reverse again
            cur.next = prev;
            prev = cur;
            cur = curNext;
            // The cur at the end of each iteration is equal to curNext, so there is no pointer crossing
        }
        // The last iteration prev points to the end of the origin, cur and curNext are null
        return prev;
    }
}

24. Nodes in a pairwise exchange chain table

Leetcode Link
Give you a list of chains, swap the adjacent nodes between them, and return the header node of the list after swapping. You must complete this topic without modifying the values within the nodes (that is, you can only exchange nodes).

Example 1:

Input: head = [1,2,3,4]
Output: [2,1,4,3]

Example 2:
Input: head = []
Output: []

Example 3:
Input: head = [1]
Output: [1]
Questions:
Because there is a relationship between the chain table and the front and back nodes, two adjacent nodes are swapped, affecting four nodes in total, one on the front and one on the back. There are three next among the four nodes, and the drawing pushes out the iteration order among the three pointers to solve the problem.

class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null) return null;
        // Virtual Header Node
        ListNode newHead = new ListNode(-1);
        newHead.next = head;
        ListNode prev = newHead;
		// Ensure that two nodes can be exchanged before entering the loop, and if only one node remains, no exchange is required
        while (prev.next != null && prev.next.next != null) {
        	// Two adjacent nodes
            ListNode node1 = prev.next;
            ListNode node2 = node1.next; 
			// Update 3 Pointers
            prev.next = node2;
            node1.next = node2.next;
            node2.next = node1;
			// Update the previous node of the next iteration
            prev = node1;
        }
        // Return to Real Head Node
        return newHead.next;
    }
}

3. Fast and slow pointers with double pointers

19. Delete the last N th node of the list of chains

Leetcode Link
Give you a list of chains, delete the last nth node of the list, and return to the header node of the list.
Example 1:
Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]

Example 2:
Input: head = [1], n = 1
Output: []

Example 3:
Input: head = [1,2], n = 1
Output: [1]

Questions:
The fast and slow pointers begin traversing at the same speed, at fixed distances from each other. When the fast pointer crosses the boundary, the slow pointer points to the previous node to be deleted, and then deletes the node.

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
    	// Using virtual by-nodes eliminates the need to deal with special cases where there is only one node
        ListNode newHead = new ListNode(-1);
        newHead.next = head;
        ListNode fast = newHead;
        ListNode slow = newHead;
        // Fast pointer goes to expected position first
        while (n >= 0 && fast != null) {
            fast = fast.next;
            n--;
        }
        // Go with the slow pointer until the fast pointer crosses the boundary
        while (fast != null) {
            slow = slow.next;
            fast = fast.next;
        }
        // At this point, the slow pointer points to the previous node to delete, deleting the node
        slow.next = slow.next.next;
        return newHead.next;
    }
}

160. Intersect Chain List

Leetcode Link
Give you the header nodes headA and headB of two single-chain lists. Find out and return the starting node where the two single-chain lists intersect. Returns null if two linked lists do not have intersecting nodes.

Diagram showing the intersection of two chains starting at node c1:
Topic data ensures that no loops exist in the entire chain structure. Note that after the function returns the result, the chain list must maintain its original structure.

Questions:
If the two chains have intersecting nodes, traverse A node first, then B node to intersection node and B node to intersection node first, then traverse A node to intersection node through the same number of nodes;
So use two nodes to traverse at the same speed, starting from different lists, and then traversing another list. If there are additional nodes, they will meet, if there are no, the last two nodes will be null at the same time.

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode nodeA = headA;
        ListNode nodeB = headB;
        while (nodeA != nodeB) {
            nodeA = nodeA.next;
            nodeB = nodeB.next;
            if (nodeA == null && nodeB == null) {
            	// If the two lists do not intersect and are null after each iteration, the loop will be dead if no more executions are return ed
                return null;
            }
            if (nodeA == null) {
                nodeA = headB;
            }
            if (nodeB == null) {
                nodeB = headA;
            }
        }
        return nodeA;
    }
}

Simplify:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode nodeA = headA;
        ListNode nodeB = headB;
        while (nodeA != nodeB) {
            nodeA = nodeA == null ? headB : nodeA.next;
            nodeB = nodeB == null ? headA : nodeB.next;
        }
        return nodeA;
    }
}

141. Ring Chain List

Leetcode Link
Give you a head node of the list to determine if there are rings in the list.

If there is a node in the chain table that can be reached again by continuously tracking the next pointer, then there are rings in the chain table. To represent rings in a given list of chains, an integer pos is used inside the evaluation system to represent where the end of the chain is connected to the list (the index starts at 0). If pos is -1, there are no rings in the list. Note: pos is not passed as a parameter, just to identify the actual situation of the chain table.

Returns true if there are rings in the chain table. Otherwise, return false.

Example 1:
Input: head = [3,2,0,-4], pos = 1 Output: true Explanation: There is a ring in the chain table whose tail is connected to the second node.
Questions:
Analogue running, if two people start at the same starting point on a straight road at different speeds, they will not meet each other. If a straight road is followed by a loop, it must meet again.

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
        	// Fast pointer takes two steps, slow pointer takes one step
            fast = fast.next.next;
            slow = slow.next;
            // Meet, return to true
            if (fast == slow) return true;
        }
        // Come to the end (null), no meeting, return false
        return false;
    }
}

142. Ring Chain List II

Leetcode Link
Given a list of chains, returns the first node where the list of chains begins to ring. If the list of chains is not looped, null is returned.

Questions:
After the fast and slow pointers encounter in the ring, the fast pointer starts from the head, the slow pointer starts from the encounter, takes one step at a time, and finally meets at the ring entry node.

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
            	// First encounter: encounter in the ring
                fast = head;
                while (fast != slow) {
                    fast = fast.next;
                    slow = slow.next;
                }
                // Second encounter: Entrance ring
                return slow;
            }
        }
        return null;
    }
}

If you don't understand it, you can also use a hash table to solve the problem:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        ListNode cur = head;
        while (cur != null) {
            if (set.contains(cur)) {
            	// Find Entering Loop Node
                return cur;
            } else {
            	// Node that first appears, added to set
                set.add(cur);
            }
            cur = cur.next;
        }
        // Not a ring list
        return null;
    }
}

4. Summary

  1. Because there is no prev node in the head node, many questions need to be dealt with separately. With virtual head node, it is not necessary to deal with this situation separately, which is convenient and concise.
  2. Be aware of pointer crossings and special considerations

Topics: Algorithm data structure leetcode linked list