def swapPairs(self, head: ListNode) -> ListNode: """ 1 2 3 4 cur p p.next t=p.next.next 3 cur.next=p.next 2 p.next.next=p 2 1 p.next=t 2 1 3 >>> Solution().swapPairs(ListNode.from_num(1234)).to_number() 2143 >>> Solution().swapPairs(ListNode.from_num(12345)).to_number() 21435 """ if not head: return head dummy = ListNode(0) dummy.next = head cur = dummy p = dummy.next while p and p.next: t = p.next.next # 交换 cur.next = p.next p.next.next = p p.next = t cur = p # 后移 p = p.next return dummy.next
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: """链表相加,值为倒序 要注意的就是找到位数差异(实际不用,因为倒序,前面的就是低位)和补上进位 比如 123 12345 之前的两个指针遍历 1 答案中结出的方法,可以判断 l1 or l2,在一个循环中完成,不要后面拼接给自己带来麻烦 >>> l1=ListNode.from_num(12) >>> l2=ListNode.from_num(9999) >>> Solution().addTwoNumbers(l1,l2).to_array() [0, 2, 0, 0, 1] >>> Solution().addTwoNumbers(ListNode.from_num(98),ListNode.from_num(1)).to_array() [0, 9] """ carry = 0 p = dummy = ListNode(0) # 使用 dump 避免最前面的判断和首次赋值 while l1 or l2: x = 0 if not l1 else l1.val y = 0 if not l2 else l2.val t = x + y + carry v, carry = t % 10, t // 10 # 余数每次都得新赋值 p.next = ListNode(v) p = p.next # p 也要后移 l1 = l1 if not l1 else l1.next l2 = l2 if not l2 else l2.next if carry: p.next = ListNode(carry) return dummy.next # 因为最前面添加了 dummy
def mergeKLists(self, lists: List[ListNode]) -> ListNode: """ 既然是已排序的,只需要依次比较就好了 超时 该方法是答案中的方法2 答案中更暴力,直接收集所以结点,然后进行排序。 1 需要重写 __lt__ >>> Solution().mergeKLists([ListNode.from_num(145),ListNode.from_num(134),ListNode.from_num(26)]).to_number() 11234456 """ p = dummy = ListNode(0) q = PriorityQueue() for i in lists: if i: q.put((i.val, i)) # 以值为优先级 while not q.empty(): val, node = q.get() # 取出的即为最小的 p.next = ListNode(val) p = p.next node = node.next if node: q.put((node.val, node)) # 如果还有 next 加入队列 return dummy.next
def deleteDuplicates(self, head: ListNode) -> ListNode: """ 好久没有链表,还是链表亲切一些,可能是因为链表的题不会太难 题目要求的是如果重复就删除,而不是只留一个 0 1 2 3 3 4 4 5 pre cur nxt 不相等,后移 pre cur nxt pre cur nxt 相等,后移 nxt pre cur nxt,将 pre.next 连接到 nxt,同时移动 cur 和 nxt pre cur nxt,继续判断 cur 和 nxt >>> Solution().deleteDuplicates(ListNode.from_num(1233445)).to_number() 125 """ if not head: # 因为后面要取 head.next 所以提前判断 return head dummy = ListNode(0) dummy.next = head pre, cur, nxt = dummy, head, head.next while cur and nxt: if cur.val != nxt.val: # 不相等,后移 pre.next = cur pre, cur, nxt = cur, nxt, nxt.next else: while nxt and cur.val == nxt.val: # 相等,查找 nxt nxt = nxt.next pre.next = nxt if nxt: cur, nxt = nxt, nxt.next return dummy.next
def mergeKLists(self, lists: List[ListNode]) -> ListNode: """ 既然是已排序的,只需要依次比较就好了 超时 该方法是答案中的方法2 答案中更暴力,直接收集所以结点,然后进行排序。 1 需要重写 __lt__ >>> Solution().mergeKLists([ListNode.from_num(145),ListNode.from_num(134),ListNode.from_num(26)]).to_number() 11234456 """ nodes = [] for i in lists: while i: nodes.append(i.val) i = i.next nodes.sort() p = dummy = ListNode(0) for i in nodes: p.next = ListNode(i) p = p.next return dummy.next
def addTwoNumbers(self, l1, l2, p=0): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ if l1 is None and l2 is None and p == 0: return None x = l1.val if l1 is not None else 0 y = l2.val if l2 is not None else 0 s = x + y + p if s >= 10: p = s // 10 s = s % 10 else: p = 0 node = ListNode(s) if l1 is not None and l2 is not None: node.next = self.addTwoNumbers(l1.next, l2.next, p) elif l1 is not None: node.next = self.addTwoNumbers(l1.next, None, p) elif l2 is not None: node.next = self.addTwoNumbers(None, l2.next, p) return node
def _make_test_case(nums, cycle_entry_index): head = ListNode(nums[0]) node, entry_node = head, head for i, num in enumerate(nums[1:]): node.next = ListNode(num) node = node.next if i + 1 <= cycle_entry_index: entry_node = entry_node.next node.next = entry_node return head, entry_node
def swapPairs(self, head: ListNode) -> ListNode: nil = ListNode(0) nil.next = head head = nil while head.next and head.next.next: p = head.next head.next = p.next p.next = head.next.next head.next.next = p head = head.next.next return nil.next
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: """链表相加,值为倒序 要注意的就是找到位数差异(实际不用,因为倒序,前面的就是低位)和补上进位 比如 123 12345 之前的两个指针遍历 O(max(m,n)) 迭代最长的链表次 空间复杂度 O(max(m,n)) 因为不是就地进行的,需要分配整个结果链表 >>> l1=ListNode.from_num(12) >>> l2=ListNode.from_num(9999) >>> Solution().addTwoNumbers(l1,l2).to_array() [0, 2, 0, 0, 1] >>> Solution().addTwoNumbers(ListNode.from_num(98),ListNode.from_num(1)).to_array() [0, 9] """ # 命名错误,不是余数 remainder = 0 p = dummy = ListNode(0) # 使用 dump 避免最前面的判断和首次赋值 while l1 and l2: t = l1.val + l2.val + remainder # 可以改用 divmod v, remainder = t % 10, t // 10 # 余数每次都得新赋值 p.next = ListNode(v) p = p.next # p 也要后移 l1 = l1.next l2 = l2.next # 移动结束,追加剩余的 if l1: p.next = l1 if l2: p.next = l2 # 追加后,如果有值,判断是否需要进位 # 这里使用 next 因为要持有 p 后面要添加进位 while p.next: t = p.next.val + remainder v, remainder = t % 10, t // 10 p.next.val = v if remainder == 0: # 没有进位,提前结束,后面也不需要再判断,也不需要再后移指针 break p = p.next # 剩余部分追加结束,或者没有追加,都要判断余数 if remainder: p.next = ListNode(remainder) return dummy.next # 因为最前面添加了 dummy
def mergeKLists(self, lists: List[ListNode]) -> ListNode: heap = MinHeap() for ls in lists: build_min_heap(heap, ls) if heap.size <= 0: return None head = node = ListNode(heap.pop_min()) while heap.size > 0: node.next = ListNode(heap.pop_min()) node = node.next return head
def list_node_from_iter(it): try: e = next(it) except StopIteration: return None root = ListNode(e) cur = root for e in it: node = ListNode(e) cur.next = node cur = node return root
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: """ 前一题的扩展 这样的 S(n) 是 O(k) 不是 O(1) 1 记数反转 dummy 1 2 3 4 pre right pre right pre right 执行反转 left left.next t 2 1 3 4 left left.next t dummy 2 1 3 4 pre right pre right 太乱了,太难理解了,不调试都无法正常运行,参考答案重新修改 >>> Solution().reverseKGroup(ListNode.from_num(12345),2).to_number() 21435 >>> Solution().reverseKGroup(ListNode.from_num(12345),3).to_number() 32145 """ dummy = ListNode(0) dummy.next = head pre = dummy right = head while True: i = 1 while right and i < k: # 后移 k-1 次,所以 i 初值为 1 i += 1 right = right.next if i == k and right is not None: # 反转 left 到 right left = h = pre.next for _ in range(k - 1): # 从 pre.next 开始反转 k-2 次 t = left.next.next # 持有第三个 left.next.next = h # 2接上头 h = left.next # 此时 2 变为头 left.next = t # 1接上3,left 不用移动,他的 next 已经变化 pre.next = h # pre 接上 头 pre = left # pre 置到最后一个 right = left.next else: return dummy.next
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: nil = ListNode(0) nil.next = head def dfs(prev, cur): if cur is None: return 1 idx = dfs(cur, cur.next) print(cur.val, idx) if idx == n: prev.next = cur.next return idx + 1 dfs(nil, head) return nil.next
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: num_nodes = 0 counter = head dummy = ListNode() dummy.next = head curr = dummy while counter: num_nodes += 1 counter = counter.next for _ in range(0, num_nodes - n): curr = curr.next # stop before the element to be removed prev = curr tmp = curr.next.next prev.next = tmp return dummy.next
def reverseList(self, head: ListNode) -> ListNode: """ 该解法是参照 https://leetcode.com/problems/reverse-linked-list/discuss/323687/9-lines-java-code.-time-less-than-100-space-less-than-almost-100 ListNode tail = null; ListNode temp; while (head != null) { temp = head.next; head.next = tail; tail = head; head = temp; } return tail; >>> Solution().reverseList(ListNode.create()) 5 -> 4 -> 3 -> 2 -> 1 >>> Solution().reverseList(ListNode.create(0)) >>> a=1 >>> b=2 >>> c=3 >>> a,b,c=b,c,a >>> print(a,b,c) 2 3 1 """ pre = None while head: # 断开并指向前 pre # pre 后移,head 后移 head.next, pre, head = pre, head, head.next return pre
def reverseList(self, head: ListNode) -> ListNode: tail = head while tail and tail.next: tail = tail.next self.reverse(head) head.next = None return tail
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: """ 前一题的扩展 这样的 S(n) 是 O(k) 不是 O(1) >>> Solution().reverseKGroup(ListNode.from_num(12345),2).to_number() 21435 >>> Solution().reverseKGroup(ListNode.from_num(12345),3).to_number() 32145 """ nodes = [] n = 0 pre = dummy = ListNode(0) dummy.next = p = head while True: while p and n < k: n += 1 nodes.append(p) p = p.next if n == k: n = 0 while nodes: pre.next = nodes.pop() pre = pre.next pre.next = p # 将 pre 接上后续的结点 else: return dummy.next
def mergeKLists(self, lists: List[ListNode]) -> ListNode: """ 既然是已排序的,只需要依次比较就好了 超时 该方法是答案中的方法2 答案中更暴力,直接收集所以结点,然后进行排序。 >>> Solution().mergeKLists([ListNode.from_num(145),ListNode.from_num(134),ListNode.from_num(26)]).to_number() 11234456 """ dummy = ListNode(0) p = dummy n = len(lists) while True: min_node = -1 for i in range(n): if lists[i] is None: continue if min_node == -1 or lists[i].val < lists[min_node].val: min_node = i # 找出最小的结点 if min_node == -1: # 没有更多结点 return dummy.next else: p.next = lists[min_node] p = p.next lists[min_node] = lists[min_node].next
def reverseList(self, head: ListNode) -> ListNode: """ 该解法是参照 https://leetcode.com/problems/reverse-linked-list/discuss/323687/9-lines-java-code.-time-less-than-100-space-less-than-almost-100 ListNode tail = null; ListNode temp; while (head != null) { temp = head.next; head.next = tail; tail = head; head = temp; } return tail; >>> Solution().reverseList(ListNode.create()) 5 -> 4 -> 3 -> 2 -> 1 >>> Solution().reverseList(ListNode.create(0)) """ pre = None while head: # 断开并指向前一个 next = head.next # 移动指针 head.next, pre, head = pre, head, next # pre 是 head 的前一个,退出循环时,head 为空,所以是返回 pre return pre
def oddEvenList(self, head: ListNode) -> ListNode: if head is None: return None nil = ListNode(-1) nil.next = head f = head.next while f is not None and f.next is not None: p = f.next f.next = p.next p.next = head.next head.next = p head = head.next f = f.next return nil.next
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: if m == n: return head dummy = ListNode() dummy.next = head pre = dummy for _ in range(m - 1): pre = pre.next # we need to connect m -> n+1 and m-1 to n after we reverse reverse = None cur = pre.next # First element to be rotated, m-th element for _ in range(n - m + 1): next = cur.next cur.next = reverse reverse = cur cur = next pre.next.next = cur pre.next = reverse return dummy.next
def insertionSortList(self, head: ListNode) -> ListNode: if head is None: return head nil = ListNode(0) nil.next = head rest = head.next head.next = None while rest is not None: p = rest rest = rest.next pre, cur = nil, nil.next while cur is not None and cur.val <= p.val: cur = cur.next pre = pre.next p.next = cur pre.next = p return nil.next
def reverseBetween(self, head, m, n): fakehead = ListNode(0) fakehead.next = head first = fakehead n -= m while m != 1: first = first.next m -= 1 if first is None or first.next is None: return head slow, fast = first.next, first.next.next while n > 0: next = fast.next fast.next = slow slow = fast fast = next n -= 1 first.next.next = fast first.next = slow return fakehead.next
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: """ https://leetcode.com/problems/merge-two-sorted-lists/discuss/9735/Python-solutions-(iteratively-recursively-iteratively-in-place). 思路简单,next 为后续合并 >>> Solution().mergeTwoLists(ListNode.create(),ListNode.create(start=2)).trim() '1223344556' >>> Solution().mergeTwoLists(ListNode.create(start=2),ListNode.create()).trim() '1223344556' """ if not l1: # 也包含 l1 l2 均为空,此时返回空 return l2 if not l2: return l1 if l1.val < l2.val: l1.next = self.mergeTwoLists(l1.next, l2) return l1 else: l2.next = self.mergeTwoLists(l1, l2.next) return l2
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: """ 前一题的扩展 这样的 S(n) 是 O(k) 不是 O(1) 1 记数反转 dummy 1 2 3 4 pre right pre right pre right 执行反转 left left.next t 2 1 3 4 left left.next t dummy 2 1 3 4 pre right pre right 太乱了,太难理解了,不调试都无法正常运行,参考答案重新修改 2 参考(别人的)答案重写 >>> Solution().reverseKGroup(ListNode.from_num(12345),2).to_number() 21435 >>> Solution().reverseKGroup(ListNode.from_num(12345),3).to_number() 32145 """ dummy = jump = ListNode(-1) dummy.next = head left = right = head while True: count = 0 while right and count < k: # 移动 k 次,当结束时,k 位于子链的后一结点,也就是下一子链的第一位 right = right.next count += 1 if count == k: # 交换 pre = right # 首次交换应该接到下一结点 cur = left for _ in range(k): nxt = cur.next # 取第2个暂存用于后移 cur.next = pre # 1连接h pre = cur # 置为 pre cur = nxt # 后移 # 连接 jump.next = pre jump = left # left 是子序列的第一位,反转后为最后一位 left = right # else: return dummy.next
def insertionSortList(self, head: ListNode) -> ListNode: if not head: return head dummy = ListNode(0) dummy.next = head lastSorted = head cur = head.next while cur: if lastSorted.val <= cur.val: lastSorted = cur else: prev = dummy while prev.next.val <= cur.val: prev = prev.next lastSorted.next = cur.next cur.next = prev.next prev.next = cur cur = lastSorted.next return dummy.next
def deleteDuplicates(self, head: ListNode) -> ListNode: """ 好久没有链表,还是链表亲切一些,可能是因为链表的题不会太难 题目要求的是如果重复就删除,而不是只留一个 0 1 2 3 3 4 4 5 pre cur nxt 不相等,后移 pre cur nxt pre cur nxt 相等,后移 nxt pre cur nxt,将 pre.next 连接到 nxt,同时移动 cur 和 nxt pre cur nxt,继续判断 cur 和 nxt 1 不需要持有 next 0 1 2 3 3 4 4 5 pre cur 后移 pre cur pre cur 相等,后移 cur pre cur,将 pre.next 指向 cur.next,同时 cur 也后移 pre cur,同样相等,后移 cur pre cur,pre.next 指向 5,后移 cur pre cur,结束,后移 pre cur >>> Solution().deleteDuplicates(ListNode.from_num(1233445)).to_number() 125 """ dummy = ListNode(0) dummy.next = head pre, cur = dummy, head while cur: if cur.next and cur.val == cur.next.val: while cur.next and cur.val == cur.next.val: # 后移 cur = cur.next pre.next = cur.next # 如果有效,pre 会移动到 pre.next,否则,会重新赋值 pre.next cur = cur.next else: # 不相等,后移 pre = pre.next cur = cur.next return dummy.next
def reverse_group(head: ListNode, k: int) -> ListNode: if not head or k < 2: return head dummy = ListNode(-1) dummy.next = head pre, end = dummy, dummy while end.next: for _ in range(k): if end: end = end.next else: break if not end: return dummy.next start, nxt, end.next = pre.next, end.next, None pre.next = reverse_list(start) start.next, pre, end = nxt, start, start return dummy.next
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: """ 旋转一部分,考虑参数异常情况 借助调试,居然过了,觉复有些复杂,去看讨论 >>> Solution().reverseBetween(ListNode.from_num(12345),2,4).to_number() 14325 """ if m >= n: return head dummy = ListNode(0) dummy.next = head i = 0 pre, cur = dummy, dummy.next reverse_pre = reverse_end = None while cur: i += 1 if i < m: pre = cur cur = cur.next elif i == m: # 开始记录 reverse_pre = pre reverse_end = cur t = cur.next cur.next = None pre = cur cur = t elif i < n: # 翻转 t = cur.next cur.next = pre pre = cur cur = t else: # 结束翻转 t = cur.next cur.next = pre reverse_pre.next = cur reverse_end.next = t break return dummy.next
def deleteDuplicates(self, head): if head is None: return None cur = head head = ListNode(0) head.next = cur par = head is_dup = False while cur.next != None: if cur.next.val == cur.val: cur.next = cur.next.next is_dup = True else: if is_dup: par.next = cur.next is_dup = False else: par = par.next cur = cur.next if is_dup: par.next = None return head.next
def partition(self, head: ListNode, x: int) -> ListNode: """ 思路就是记录两个链表 和答案一致,但是答案标明的是 Approach 1,可能还有别的解法 否则就如评论所说,这应该是 easy 难度,我也就只能做做 easy 难度了 T...T >>> Solution().partition(ListNode.from_num(143252),3).to_number() 122435 """ p1 = dummy1 = ListNode(0) p2 = dummy2 = ListNode(0) p = head while p: if p.val < x: # 前 p1.next = p p1 = p else: p2.next = p p2 = p p = p.next p1.next = None # 多余 p2.next = None p1.next = dummy2.next return dummy1.next
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: """链表相加,值为倒序 要注意的就是找到位数差异(实际不用,因为倒序,前面的就是低位)和补上进位 比如 123 12345 之前的两个指针遍历 1 答案中结出的方法,可以判断 l1 or l2,在一个循环中完成,不要后面拼接给自己带来麻烦 2 讨论中的优化,不需要 x,y >>> l1=ListNode.from_num(12) >>> l2=ListNode.from_num(9999) >>> Solution().addTwoNumbers(l1,l2).to_array() [0, 2, 0, 0, 1] >>> Solution().addTwoNumbers(ListNode.from_num(98),ListNode.from_num(1)).to_array() [0, 9] """ carry = 0 p = dummy = ListNode(0) # 使用 dump 避免最前面的判断和首次赋值 while l1 or l2: if l1: carry += l1.val l1 = l1.next if l2: carry += l2.val l2 = l2.next carry, v = divmod(carry, 10) p.next = ListNode(v) p = p.next if carry: p.next = ListNode(carry) return dummy.next
def rotateRight(self, head, k): if not head or k <= 0: return head num = 0 node = head while node: node = node.next num += 1 k = k % num if k == 0: return head fast = head for i in range(k): fast = fast.next slow = head while fast.next: slow = slow.next fast = fast.next fast.next = head head = slow.next slow.next = None return head node = ListNode.from_list([1]) s = Solution() print(s.rotateRight(node, 1))
def new_node(val, next): node = ListNode(val) node.next = next return node
head = None curr = None while nodes: n = len(nodes) minv = float('inf') index = 0 for i in range(n): node = nodes[i] if node.val < minv: minv = node.val index = i if not head: head = ListNode(minv) curr = head else: curr.next = ListNode(minv) curr = curr.next node = nodes[index].next if not node: nodes.pop(index) else: nodes[index] = node return head a = ListNode.from_list([1,2,3]) b = ListNode.from_list([2,3,4]) s = Solution() print(s.mergeKLists([a,b]))
# @return a tree node def sortedListToBST(self, head): if not head: return None if not head.next: node = TreeNode(head.val) return node fast = head slow = head prev = None while fast.next and fast.next.next: fast = fast.next.next prev = slow slow = slow.next node = TreeNode(slow.val) right = slow.next if prev: prev.next = None node.left = self.sortedListToBST(head) else: node.left = self.sortedListToBST(None) node.right = self.sortedListToBST(right) return node a = [1,2,3,4] l = ListNode.from_list(a) s = Solution() print(s.sortedListToBST(l))
while tail and tail.next and count < k: count += 1 tail = tail.next if count != k: break node = head next = node.next for i in range(k-1): tmp = next.next next.next = node node = next next = tmp if not prev: newhead = tail else: prev.next = tail prev = head head.next = tmp head = tmp tail = head if not newhead: newhead = head return newhead a = ListNode.from_list([1,2,3,4,5,6]) s = Solution() print(s.reverseKGroup(a, 2))