Chain Table Paper
24.Nodes in a two-way exchange chain table
- Idea 1: Introduce sentinel node, adopt double pointer pre, cur
class Solution(object): def swapPairs(self, head): auxi = ListNode(0,next = head) pre,cur = auxi,head while cur and cur.next: tmp = cur.next cur.next = tmp.next tmp.next = cur pre.next = tmp pre = cur cur = cur.next return auxi.next
Summary: Sentry nodes can be introduced when the head node is uncertain
141.Circular linked List
- Idea 1: Fast and slow pointers, if looped, must intersect
- Idea 2: Record visited nodes with a collection, and loop if present
#Idea 1: Fast and slow pointers class Solution(object): def hasCycle(self, head): if not head: return head fast,slow = head,head while fast and fast.next: slow = slow.next fast = fast.next.next if slow==fast: return True return False #Idea 2: Collection class Solution(object): def hasCycle(self, head): myset = set() while head: if head not in myset: myset.add(head) else: return True head = head.next return False
Summary: Chain lists are looped with fast and slow pointers
142.Ring Chain Table II
- Idea 1: Fast and slow pointers. If they are looped, the head node and the fast and slow pointer intersect each other next. The final intersection is the ring intersect node
- Idea 2: Record visited nodes with a collection, and if looped, the first node that repeats is the intersecting node
#Idea 1: Fast and slow pointers class Solution(object): def detectCycle(self, head): if not head or not head.next: return None pre,cur = head,head while cur and cur.next: pre = pre.next cur = cur.next.next if pre == cur: # Represents Ring p1 = head p2 = cur while p1!=p2: p1 = p1.next p2 = p2.next return p1 return None #Idea 2: Collection class Solution(object): def detectCycle(self, head): mySet = set() while(head): if head not in mySet: mySet.add(head) else: return head head = head.next return None
Summary: Chain lists are looped with fast and slow pointers
86.Separated Chain List
- Idea 1: For the question of separating the elements of a chain table, consider introducing multiple sentinel nodes, joining different sub-chain lists, and then stitching them together
- Idea 2: Separate the linked list nodes with two extra arrays, then stitch the arrays, and join the nodes of the arrays back and forth
# Idea 1: Sentinel Node class Solution(object): def partition(self, head, x): if not head: return None auxi1,auxi2 = ListNode(0),ListNode(0) cur1,cur2 = auxi1,auxi2 while head: if head.val < x: cur1.next = head cur1 = cur1.next else: cur2.next = head cur2 = cur2.next head = head.next cur1.next = auxi2.next cur2.next = None return auxi1.next # With arrays class Solution(object): def partition(self, head, x): if not head: return None nums1,nums2 = [],[] while head: if head.val < x: nums1.append(head) else: nums2.append(head) head = head.next nums1.extend(nums2) for i in range(len(nums1)-1): nums1[i].next = nums1[i+1] nums1[-1].next = None return nums1[0]
Summary: Multiple Sentinel Nodes are introduced to separate, and the last element of the chain table points to None
328.Parity Chain List
- Idea 1: For the question of separating the elements of a chain table, consider introducing multiple sentinel nodes, joining different sub-chain lists, and then stitching them together
- Idea 2: Separate the linked list nodes with two extra arrays, then stitch the arrays, and join the nodes of the arrays back and forth
# Idea 1: Sentinel Node class Solution(object): def oddEvenList(self, head): auxi1,auxi2 = ListNode(0),ListNode(0) cur1,cur2 = auxi1,auxi2 cnt = 0 while head: cnt += 1 if cnt % 2!= 0 : cur1.next = head cur1 = cur1.next else: cur2.next = head cur2 = cur2.next head = head.next cur1.next = auxi2.next cur2.next = None return auxi1.next # With arrays class Solution(object): def oddEvenList(self, head): if not head: return None nums1,nums2 = [],[] cnt = 1 while head: if cnt%2==1: nums1.append(head) else: nums2.append(head) cnt += 1 head = head.next nums1.extend(nums2) for i in range(len(nums1)-1): nums1[i].next = nums1[i+1] nums1[-1].next = None return nums1[0]
Summary: Multiple Sentinel Nodes are introduced to separate, and the last element of the chain table points to None
19.Delete the last N th node in the list of chains
- Idea 1: Fast slow pointer, slow pointer walk n steps later than fast pointer
class Solution(object): def removeNthFromEnd(self, head, n): tmp = ListNode(0) tmp.next = head pre,cur = tmp,head cnt = 0 while head: cnt += 1 if cnt > n: # Slow pointer walk n steps late pre = cur cur = cur.next head = head.next pre.next = cur.next # Fast and slow pointers delete the last nth node return tmp.next
22.The last k th node in the list of chains
- Idea 1: Fast slow pointer, slow pointer walk k steps later than fast pointer
class Solution(object): def getKthFromEnd(self, head, k): pre,cur = head,head cnt = 0 while cur: cnt += 1 if cnt>k: pre = pre.next cur = cur.next return pre
61.Rotating Chain List
- Idea 1: First traverse to the end of the list and record the length L of the list, the end node points to the head node to form a ring, then points to the head node pointer cur to move L-k times, break the loop, cur is the new head node
class Solution(object): def rotateRight(self, head, k): if not head: return head cnt,cur,pre = 0,head,head while cur: cnt += 1 pre = cur cur = cur.next pre.next = head # Ring pre,cur = head,head k = cnt - k % cnt while cur: k -= 1 pre = cur cur = cur.next if k == 0: pre.next = None break return cur
Summary: The last element of the list points to None
138.Copy a chain table with random pointers
- Idea 1: Copy one node after each node of the original chain table, and then separate according to parity to get a new copy list
- Idea 2: Introduce a dictionary, iterate through the list of chains, record old nodes and new nodes one-to-one. The random pointer of the new node points to the position, which can be obtained by looking up the dictionary according to the pointing position of the old node corresponding to the new node.
# Idea One class Solution(object): def copyRandomList(self, head): if not head: return None cur = head while cur: tmp = cur.next cur.next = Node(cur.val,next=tmp,random=cur.random) cur = tmp cur = head while cur: tmp = cur.next.next if cur.random: cur.next.random = cur.random.next else: cur.next.random = None cur = tmp ret,pre,cur = head.next,head,head.next while cur and cur.next: tmp1 = pre.next.next tmp2 = tmp1.next pre.next = tmp1 cur.next = tmp2 cur = tmp2 pre = tmp1 cur.next = None pre.next = None return ret # Idea Two class Solution(object): def copyRandomList(self, head): auxi = Node(0) pre,mydict = auxi,{} while head: tmp = Node(head.val) pre.next = tmp pre = tmp mydict[head] = tmp head = head.next for k,v in mydict.items(): if k.random: v.random = mydict[k.random] # k.random is not None before a dictionary is saved else: v.random = None return auxi.next
Summary: Copying a list of chains allows you to copy a copy between each node of the original list, then separate it; there is a one-to-one correspondence that can be introduced into a dictionary.
146.LRU Cache Mechanism
- Idea 1: Using the form of two-way Chain Table + dictionary, dictionary for fast lookup, two-way chain table for updating the most recently visited data nodes to head, the most recently visited nodes are found and deleted by tail
# Core Idea: Two-way Chain List + Dictionary class DlinkNode(object): def __init__(self,key=0,val=0): self.key = key self.val = val self.pre = None self.next = None class LRUCache(object): def __init__(self, capacity): self.head = DlinkNode() self.tail = DlinkNode() self.head.next = self.tail self.tail.pre = self.head self.capacity = capacity self.size = 0 self.cache = {} def get(self, key): if key not in self.cache: return -1 else: node = self.cache[key] self.moveToHead(node) return node.val def put(self, key, value): if key in self.cache: self.cache[key].val = value self.moveToHead(self.cache[key]) else: node = DlinkNode(key,value) if self.size == self.capacity: tail = self.removeTail() self.cache.pop(tail.key) self.size -= 1 self.cache[key] = node self.addToHead(node) self.size += 1 def removeNode(self,node): node.pre.next = node.next node.next.pre = node.pre def addToHead(self,node): self.head.next.pre = node node.next = self.head.next node.pre = self.head self.head.next = node def moveToHead(self,node): self.removeNode(node) self.addToHead(node) def removeTail(self): node = self.tail.pre self.removeNode(node) return node
Summary: LRU cache uses the idea of two-way Chain Table + dictionary