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 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 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 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 addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: l1stack, l2stack = [], [] while l1: l1stack.append(l1.val) l1 = l1.next while l2: l2stack.append(l2.val) l2 = l2.next len1, len2 = len(l1stack), len(l2stack) if len1 >= len2: long, short = l1stack, l2stack else: short, long = l1stack, l2stack i = 0 carry = 0 head_node, cur_node = None, None while i < len(short): v_sum = short[i] + long[i] + carry if v_sum >= 10: carry = 1 v_sum = v_sum - 10 else: carry = 0 if not head_node: cur_node = ListNode(v_sum) head_node = cur_node else: next_node = ListNode(v_sum) cur_node.next = next_node cur_node = next_node i += 1 while i < len(long): v_sum = long[i] + carry if v_sum >= 10: carry = 1 v_sum = v_sum - 10 else: carry = 0 next_node = ListNode(v_sum) cur_node.next = next_node cur_node = next_node i += 1 if carry: next_node = ListNode(carry) cur_node.next = next_node return head_node
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 mergeInBetween(self, list1: ListNode, a: int, b: int, list2: ListNode) -> ListNode: start, end = None, list1 for i in range(b): if i == a - 1: start = end end = end.next start.next = list2 while list2.next: list2 = list2.next list2.next = end.next end.next = None return list1
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 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 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 addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: stack1, stack2 = [], [] while l1: stack1.append(l1.val) l1 = l1.next while l2: stack2.append(l2.val) l2 = l2.next prev, head = None, None sum = 0 while stack1 or stack2: sum //= 10 if stack1: sum += stack1.pop() if stack2: sum += stack2.pop() head = ListNode(sum % 10) head.next = prev prev = head if sum >= 10: head = ListNode(sum // 10) head.next = prev return head
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 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 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 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 reverseList(self, head: ListNode) -> ListNode: """TODO 涉及到链表的操作,一定要在纸上把过程先画出来,再写程序 https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode/ 假设列表的其余部分已经被反转,现在我该如何反转它前面的部分 如 N1->N2->..->Nk->N(k+1)<-..<-Nm<- ∅ 我们正处于Nk 所以 Nk.next.next=Nk """ if not (head and head.next): return head p = self.reverseList(head.next) head.next.next = head head.next = None return p
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 isPalindrome(self, head: ListNode) -> bool: reverse, fast = None, head # Reverse the first half part of the list. while fast and fast.next: fast = fast.next.next head.next, reverse, head = reverse, head, head.next # If the number of the nodes is odd, # set the head of the tail list to the next of the median node. tail = head.next if fast else head # print(head,reverse,tail) # Compare the reversed first half list with the second half list. # And restore the reversed first half list. while reverse: if reverse.val != tail.val: return False reverse.next, head, reverse = head, reverse, reverse.next tail = tail.next return True
def plusOne(self, head: ListNode) -> ListNode: """TODO""" def helper(node): if not node: return 1 carry = helper(node.next) sum_val = carry + node.val node.val = sum_val % 10 return sum_val // 10 if not head: return head carry = helper(head) if carry: res = ListNode(1) res.next = head return res return head
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: """ 92 :param head: :param m: :param n: :return: """ if m == n: return head infix_tail = None infix_head = None node = None idx = 1 while idx < m: if node is None: node = head else: node = node.next idx += 1 prefix_tail = node while idx <= n: if node is None: node = head else: node = node.next infix_node = ListNode(node.val) if infix_head is None: infix_head = infix_tail = infix_node else: infix_node.next = infix_head infix_head = infix_node idx += 1 if prefix_tail is None: new_head = infix_head else: new_head = head prefix_tail.next = infix_head infix_tail.next = node.next return new_head
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: hair = ListNode(-1) hair.next = head pre = hair while head: tail = pre # 查看剩余部分长度是否大于等于 k for i in range(k): tail = tail.next if not tail: return hair.next tmp = tail.next head, tail = self.reverse(head, tail) # 把子链表重新接回原链表 pre.next = head tail.next = tmp pre = tail head = tail.next return hair.next
def plusOne(self, head: ListNode) -> ListNode: # sentinel head sentinel = ListNode(0) sentinel.next = head not_nine = sentinel # find the rightmost not-nine digit while head: if head.val != 9: not_nine = head head = head.next # increase this rightmost not-nine digit by 1 not_nine.val += 1 not_nine = not_nine.next # set all the following nines to zeros while not_nine: not_nine.val = 0 not_nine = not_nine.next return sentinel if sentinel.val else sentinel.next
def swapPairs(self, head: ListNode) -> ListNode: # Dummy node acts as the prevNode for the head node # of the list and hence stores pointer to the head node. dummy = ListNode(-1) dummy.next = head prev_node = dummy while head and head.next: # Nodes to be swapped first_node = head second_node = head.next # Swapping prev_node.next = second_node first_node.next = second_node.next second_node.next = first_node # Reinitializing the head and prev_node for next swap prev_node = first_node head = first_node.next # Return the new head node. return dummy.next
def reverse(self, a: ListNode, b: ListNode): prev, cur = ListNode(-1), a while cur != b: prev.next, cur.next, cur = cur, prev.next, cur.next return prev.next
def reverseList(self, head: ListNode) -> ListNode: dummy = ListNode(-1) cur = head while cur: dummy.next, cur.next, cur = cur, dummy.next, cur.next return dummy.next