def removeZeroSumSublists(self, head: ListNode) -> ListNode: """ TODO 前缀和 掌握 ; so Amazing 我们可以考虑如果给的入参不是链表是数组的话,只需要求出前缀和,对于前缀和相同的项, 那他们中间的部分即是可以消除掉的,比如以 [1, 2, 3, -3, 4] 为例,其前缀和数组为 [1, 3, 6, 3, 7] , 我们发现有两项均为 3,则 6 和 第二个 3 所对应的原数组中的数字是可以消掉的。 换成链表其实也是一样的思路,把第一个 3 的 next 指向第二个 3 的 next 即可 """ seen = dict() dummy = ListNode(0) dummy.next = head # // 首次遍历建立 节点处链表和<->节点 哈希表 # // 若同一和出现多次会覆盖,即记录该sum出现的最后一次节点 prefix = 0 cur = dummy while cur: prefix += cur.val seen[prefix] = cur cur = cur.next cur2 = dummy prefix = 0 # // 第二遍遍历 若当前节点处sum在下一处出现了则表明两结点之间所有节点和为0 直接删除区间所有节点 while cur2: prefix += cur2.val cur2.next = seen[prefix].next cur2 = cur2.next return dummy.next
def partition(self, head: ListNode, x: int) -> ListNode: """ 86 :param head: :param x: :return: """ if not head: return head less_head = less_node = None equal_more_than_head = equal_more_than_node = None node = head while node: val = node.val if val < x: if less_head is None: less_head = less_node = ListNode(val) else: less_node.next = ListNode(val) less_node = less_node.next else: if equal_more_than_head is None: equal_more_than_head = equal_more_than_node = ListNode(val) else: equal_more_than_node.next = ListNode(val) equal_more_than_node = equal_more_than_node.next node = node.next if less_head is None: new_head = equal_more_than_head else: less_node.next = equal_more_than_head new_head = less_head return new_head
def removeZeroSumSublists(self, head: ListNode) -> ListNode: """ """ vals = [] cur = head while cur: if cur.val != 0: vals.append(cur.val) cur = cur.next i = 0 while 0 <= i < len(vals): sum = vals[i] j = i + 1 while j < len(vals): sum += vals[j] if sum == 0: vals[i:j + 1] = [] i = i - 1 break j += 1 i += 1 dummy = ListNode(-1) pos = dummy for v in vals: pos.next = ListNode(v) pos = pos.next return dummy.next
def test_solutions(): inter = ListNode.initList([1, 8, 4, 5]) headA = ListNode.initList([4]) headB = ListNode.initList([5, 0]) headA.next = inter headB.next = inter res = Solution().getIntersectionNode(headA, headB) assert res == inter
def test_solutions(): l1 = ListNode.initList([4, 1, 8, 4, 5]) l2 = ListNode.initList([5, 0]) l2.next.next = l1.next res = Solution().getIntersectionNode(l1, l2) res1 = Solution1().getIntersectionNode(l1, l2) assert res == l1.next assert res1 == l1.next
def deleteNode(self, head: ListNode, val: int) -> ListNode: dummy = ListNode(-1) dummy.next = head prev, cur = dummy, head while cur: if cur.val == val: break prev, cur = cur, cur.next prev.next = cur.next return dummy.next
def test_solution(): cycle = ListNode.initList([2, 0, -4]) cur = cycle while cur.next: cur = cur.next cur.next = cycle head = ListNode(3) head.next = cycle res = Solution().detectCycle(head) assert res and res.val == 2
def test_swapPairs(self): node1 = ListNode(1) node2 = ListNode(2) node1.next = node2 node3 = ListNode(3) node2.next = node3 node4 = ListNode(4) node3.next = node4 print_linked_list(node1) # node = self.sln.swapPairs(node1) node = self.sln.swapPairs(node2) print_linked_list(node)
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: dummy = ListNode(-1) dummy.next = head first = head second = dummy for i in range(n): first = first.next while first: first = first.next second = second.next second.next = second.next.next return dummy.next
def deleteNodes(self, head: ListNode, m: int, n: int) -> ListNode: dummy = ListNode(-1) dummy.next = head cur = dummy while cur.next: p, q = m, n while p and cur.next: cur = cur.next p -= 1 while q and cur.next: cur.next = cur.next.next q -= 1 return dummy.next
def addAtIndex(self, index: int, val: int) -> None: """ Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. """ if not 0 <= index <= self.__size: return pre = self.__dummy_head node = ListNode(val) for _ in range(index): pre = pre.next node.next = pre.next pre.next = node self.__size += 1
def deleteDuplicates(self, head: ListNode) -> ListNode: dummy = ListNode(-1) dummy.next = head cur = dummy while cur.next and cur.next.next: if cur.next.val == cur.next.next.val: x = cur.next.val while cur.next and cur.next.val == x: cur.next = cur.next.next else: cur = cur.next return dummy.next
def mergeKLists(self, lists: List[ListNode]) -> ListNode: """Me O(NlogN) """ min_heap = [] heapq.heapify(min_heap) for head in lists: while head: heapq.heappush(min_heap, head.val) head = head.next dummyHead = ListNode(-1) cur_head = dummyHead while min_heap: val = heapq.heappop(min_heap) cur_head.next = ListNode(val) cur_head = cur_head.next return dummyHead.next
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: dummy_head = ListNode(None) dummy_head.next = head first = dummy_head second = dummy_head for i in range(1, n + 1): first = first.next while first.next: first = first.next second = second.next if second.next: second.next = second.next.next else: second.next = None return dummy_head.next
def deleteNodes(self, head: ListNode, m: int, n: int) -> ListNode: dummy = ListNode(-1) dummy.next = head cur = head pre = None while cur: p, q = m, n while p and cur: pre = cur cur = cur.next p -= 1 while q and cur: cur = cur.next q -= 1 pre.next = cur return dummy.next
def reorderList(self, head: ListNode) -> None: """ Do not return anything, modify head in-place instead. TODO """ if not (head and head.next): return fast, slow, prev = head, head, None while fast and fast.next: fast, slow, prev = fast.next.next, slow.next, slow current, prev.next, prev = slow, None, None while current: current.next, prev, current = prev, current, current.next l1, l2 = head, prev dummy = ListNode(-1) current = dummy while l1 and l2: current.next = l1 current = l1 l1 = l1.next # print(dummy,current, l1, l2, sep="\t") current.next, current, l2 = l2, l2, l2.next
def reverseList(self, head: ListNode) -> ListNode: if not (head and head.next): return head p = self.reverseList(head.next) head.next.next = head head.next = None return p
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: """ Common """ dummy = ListNode(-1) p = dummy while True: count = k stack = [] cur = head while count and cur: stack.append(cur) cur = cur.next count -= 1 # 注意,目前tmp所在k+1位置 # 说明剩下的链表不够k个,跳出循环 if count: p.next = head break # 翻转操作 while stack: p.next = stack.pop() p = p.next # 与剩下链表连接起来 不需要 # p.next = cur head = cur return dummy.next
def partition(self, head: ListNode, x: int) -> ListNode: dummy = ListNode(-1) right_dummy = ListNode(-1) cur = dummy right_cur = right_dummy while head: if head.val < x: cur.next = head cur = head else: right_cur.next = head right_cur = right_cur.next head = head.next right_cur.next = None cur.next = right_dummy.next return dummy.next
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: """ TODO : 尾插法。 Recurse """ cur = head # print("HEAD_RAW | ",cur) cnt = 0 while cur and cnt != k: cur = cur.next cnt += 1 # print("cur before recurse | ",head,cur,k) if cnt == k: cur = self.reverseKGroup(cur, k) # print("cur after recurse HEAD |",head,"\t\tCUR",cur) while cnt: tmp = head.next head.next = cur cur = head head = tmp cnt -= 1 head = cur return head
def numComponents(self, head: ListNode, G: List[int]) -> int: """ TODO 题义转换 我们对链表进行一次扫描,一个组件在链表中对应一段极长的连续节点,因此如果当前的节点在列表 G 中, 并且下一个节点不在列表 G 中,我们就找到了一个组件的尾节点,可以将答案加 1 """ lookup = set(G) dummy = ListNode(-1) dummy.next = head cur = dummy result = 0 while cur and cur.next: if cur.val not in lookup and cur.next.val in lookup: result += 1 cur = cur.next return result
def splitListToParts(self, root: ListNode, k: int) -> List[ListNode]: """Me""" if not root: return [None] * k n = 0 cur = root while cur: n += 1 cur = cur.next rest = n % k divide = n // k cur_pos = root # print(rest,divide) res = [ListNode(-1) for _ in range(k)] for i in range(k): ith_node = res[i % k] ith_node.next = cur_pos if not cur_pos: continue else: cnt = divide if rest > 0: rest -= 1 cnt += 1 for _ in range(cnt - 1): cur_pos = cur_pos.next if cur_pos: tmp = cur_pos.next cur_pos.next = None cur_pos = tmp return [x.next for x in res]
def swapPairs(self, head: ListNode) -> ListNode: """ME""" if not (head and head.next): return head dummy = ListNode(-1) cur_head = dummy while head and head.next: now_tail = head.next.next cur_pre = head.next head.next = now_tail cur_pre.next = head cur_head.next = cur_pre cur_head = cur_head.next.next head = cur_pre.next.next return dummy.next
def test_solutions(): head = ListNode.initList([3, 2, 0, -4]) cur = head while cur.val != 0: cur = cur.next cur.next = head res = Solution().detectCycle(head) assert res.val == 3
def test_solution(): l = ListNode.initList([3, 2, 0, -4]) assert not Solution().hasCycle(l) cur = l while cur.next: cur = cur.next cur.next = l assert Solution().hasCycle(l)
def insertionSortList(self, head: ListNode) -> ListNode: """TODO""" if not (head and head.next): return head dummy = ListNode(None) dummy.next = head cur, sorted_tail = head.next, head while cur: prev = dummy while prev.next.val < cur.val: prev = prev.next if prev == sorted_tail: cur, sorted_tail = cur.next, cur else: cur.next, prev.next, sorted_tail.next = prev.next, cur, cur.next cur = sorted_tail.next return dummy.next
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: dummy = ListNode(-1) ans = dummy carry = 0 while l1 or l2: if l1: carry += l1.val l1 = l1.next if l2: carry += l2.val l2 = l2.next ans.next = ListNode(carry % 10) ans = ans.next carry //= 10 if carry: ans.next = ListNode(carry) return dummy.next
def mergeKLists(self, lists: List[ListNode]) -> ListNode: """ O(N*logk) k是链表数目 ;LeetCode无法运行? O(n) """ Q = PriorityQueue() for l in lists: if l: Q.put((l.val, l)) dummyHead = ListNode(-1) cur_head = dummyHead while not Q.empty(): val, node = Q.get() cur_head.next = ListNode(val) cur_head = cur_head.next node = node.next if node: Q.put((node.val, node)) return dummyHead.next
def listOfDepth(self, tree: TreeNode) -> List[ListNode]: res = [] if not tree: return res stack = [tree] while stack: n = len(stack) head = ListNode(-1) cur = head for i in range(n): node = stack.pop(0) if node.left: stack.append(node.left) if node.right: stack.append(node.right) cur.next = ListNode(node.val) cur = cur.next res.append(head.next) return res
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: cur = dum = ListNode(0) while l1 and l2: if l1.val < l2.val: cur.next, l1 = l1, l1.next else: cur.next, l2 = l2, l2.next cur = cur.next cur.next = l1 if l1 else l2 return dum.next