def test_linked_list_cycle(self): def addCycle(node, num): if num == -1 and not node: return i = 0 cur_node = None while node.next: if i == num: cur_node = node i = i + 1 node = node.next node.next = cur_node s = Solution() # 重载了equal,因此有环时==有问题 node1 = ListNode.generate([3, 2, 0, -4]) addCycle(node1, 1) self.assertEqual(True, s.hasCycle(node1)) node2 = ListNode.generate([1, 2]) addCycle(node2, 0) self.assertEqual(True, s.hasCycle(node2)) node3 = ListNode.generate([1]) addCycle(node3, -1) self.assertEqual(False, s.hasCycle(node3))
def kSimilarity1(self, A, B): """ :type A: str :type B: str :rtype: int """ dummy1, dummy2 = ListNode('s'), ListNode('s') cur1, cur2 = dummy1, dummy2 for c in zip(A, B): cur1.next, cur2.next = ListNode(c[0]), ListNode(c[1]) cur1, cur2 = cur1.next, cur2.next cur1, cur2 = dummy1, dummy2 step = 0 while cur1.next: cur2_1 = cur2 while cur1.next.val != cur2.next.val: cur2 = cur2.next step += 1 if cur2_1 != cur2: tmp = cur2.next # python的多重赋值是否可以简化? cur2.next = cur2.next.next tmp.next = cur2_1.next cur2_1.next = tmp cur2 = cur2_1 cur1, cur2 = cur1.next, cur2.next return step
def swap_pairs(head: ListNode) -> ListNode: """ :type head: ListNode :rtype: 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 deleteDuplicates2(self, head: ListNode) -> ListNode: # side case if not head or not head.next: return head # dummy node: In case of the LinkedList's head maybe deleted. 'dummy.next' will point to new head when origin head was deleted. dummy = ListNode(0) dummy.next = head # 提前想好要用几个辅助变量。本题很明显需要维护当前节点和当前节点的前一个节点一共俩,直接声明变量赋值,不要乱用head,会导致指向混乱。 pre = dummy cur = head # 循环体为cur node节点 while cur: # 碰到cur和cur.next值相等,直接将cur后移,直到不相等 while cur.next and cur.val == cur.next.val: cur = cur.next # 以下是cur和cur.next值不相等的情况(此处方法是用if判断,因为假如没有发生过while cur后移操作的话,pre.next应当是指向cur的;而我自己的方法是增加flag变量,学!) if pre.next == cur: # 没有发生过while cur后移操作:直接将pre后移 pre = pre.next else: # 发生过while cur后移操作:维护pre.next链,pre不用动 pre.next = cur.next cur = cur.next return dummy.next
def mergeTwoLists(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ n1 = ListNode(0) # 优化:先找到小的头节点,可以无需添加dummy节点 n1.next, n2 = l1, l2 head = n1 while n1.next and n2: if n1.next.val <= n2.val: n1 = n1.next else: p = n2 n2 = n2.next p.next = n1.next n1.next = p n1 = n1.next if n2: n1.next = n2 return head.next
def add_two(l1, l2): if l1 is None: return l2 elif l2 is None: return l1 else: carry = 0 result = ListNode(0) temp = result while l1 or l2: sum_total = 0 if l1: sum_total = l1.val l1 = l1.next if l2: sum_total += l2.val l2 = l2.next sum_total += carry temp.next = ListNode(sum_total % 10) temp = temp.next carry = (sum_total >= 10) if carry: temp.next = ListNode(1) temp = result.next del result return temp
def test_facebook(self): s = Solution() self.assertEqual( ListNode.generate([1, 1, 2, 3, 4, 4]), s.mergeTwoLists(ListNode.generate([1, 2, 4]), ListNode.generate([1, 3, 4])))
def addTwoNumbers(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ def add(n1, n2, c): # Return result and carry on. r = n1 + n2 + c return r % 10, r / 10 dummy = ListNode(None) p, p1, p2 = dummy, l1, l2 c = 0 while p1 and p2: r, c = add(p1.val, p2.val, c) p.next = ListNode(r) p, p1, p2 = p.next, p1.next, p2.next p1 = p1 if p1 else p2 while p1: r, c = add(p1.val, 0, c) p.next = ListNode(r) p, p1 = p.next, p1.next if c > 0: p.next = ListNode(c) return dummy.next
def test_facebook(self): s = Solution() self.assertEqual( ListNode.generate([7, 0, 8]), s.addTwoNumbers(ListNode.generate([2, 4, 3]), ListNode.generate([5, 6, 4])))
def merge_sort(head: ListNode, length: int) -> Tuple[ListNode, ListNode]: # Sort list for given length, return sorted list and list after length. if not head: return (None, None) if length == 1: next_head = head.next head.next = None return (head, next_head) new_head_1, next_to_sort_1 = merge_sort(head, length // 2) new_head_2, next_to_sort_2 = merge_sort(next_to_sort_1, length // 2 + length % 2) # Merge new_head_1 and new_head_2. p = dummy = ListNode(0) p1, p2 = new_head_1, new_head_2 while p1 or p2: v1 = p1.val if p1 else float('inf') v2 = p2.val if p2 else float('inf') if v1 <= v2: p.next = p1 p1 = p1.next else: p.next = p2 p2 = p2.next p = p.next return (dummy.next, next_to_sort_2)
def addTwoNumbers1(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ carry = 0 # 进位标记符 head = ListNode(0) # 标记用头节点,最终需要去掉,或在循环体内判断ListNode是否为None current = head while l1 or l2: val = carry if l1: val += l1.val l1 = l1.next if l2: val += l2.val l2 = l2.next if val >= 10: # 参考答案用了divmod除法函数 carry, val = divmod(val, 10) val -= 10 carry = 1 else: carry = 0 current.next = ListNode(val) current = current.next if carry == 1: current.next = ListNode(carry) return head.next
def test_remove_duplicates_from_sorted_list_ii(self): s = Solution() self.assertEqual(ListNode.generate([]), s.deleteDuplicates(ListNode.generate([]))) self.assertEqual(ListNode.generate([1]), s.deleteDuplicates(ListNode.generate([1]))) self.assertEqual(ListNode.generate([]), s.deleteDuplicates(ListNode.generate([1, 1]))) self.assertEqual(ListNode.generate([1, 2, 5]), s.deleteDuplicates(ListNode.generate([1, 2, 3, 3, 4, 4, 5]))) self.assertEqual(ListNode.generate([2, 3]), s.deleteDuplicates(ListNode.generate([1, 1, 1, 2, 3])))
def test_19_removeNthFromEnd(self): head = ListNode(1) head.next = ListNode(2) head.next.next = ListNode(3) head = self.solution._19_removeNthFromEnd(head, 3) self.assertEqual(2, head.val) self.assertEqual(3, head.next.val)
def test_remove_linked_list_elements(self): s = Solution() self.assertEqual(None, s.removeElements(ListNode.generate([]), 6)) self.assertEqual(None, s.removeElements(ListNode.generate([6, 6]), 6)) self.assertEqual(None, s.removeElements(ListNode.generate([6]), 6)) self.assertEqual(ListNode.generate([1, 2, 3, 4, 5]), s.removeElements(ListNode.generate([1, 2, 6, 3, 4, 5, 6]), 6))
def test_24_swapPairs(self): head = ListNode(1) head.next = ListNode(2) head.next.next = ListNode(3) head = self.solution._24_swapPairs(head) self.assertEqual(2, head.val) self.assertEqual(1, head.next.val) self.assertEqual(3, head.next.next.val)
def addTwoNumbers2(self, l1, l2): def toint(node): return node.val + 10 * toint(node.next) if node else 0 n = toint(l1) + toint(l2) first = last = ListNode(n % 10) while n > 9: n /= 10 last.next = last = ListNode(n % 10) return first
def addTwoNumbers1(self, l1, l2): addends = l1, l2 dummy = end = ListNode(0) carry = 0 while addends or carry: carry += sum(a.val for a in addends) addends = [a.next for a in addends if a.next] end.next = end = ListNode(carry % 10) carry /= 10 return dummy.next
def test_partition_list(self): s = Solution() # self.assertEqual(ListNode.generate([1, 2, 2, 4, 3, 5]), s.partition(ListNode.generate([1, 4, 3, 2, 5, 2]), 3)) # self.assertEqual(ListNode.generate([1, 4]), s.partition(ListNode.generate([4, 1]), 3)) # self.assertEqual(ListNode.generate([]), s.partition(ListNode.generate([]), 3)) # self.assertEqual(ListNode.generate([1, 2, 3]), s.partition(ListNode.generate([2, 1, 3]), 2)) # self.assertEqual(ListNode.generate([1]), s.partition(ListNode.generate([1]), 2)) # self.assertEqual(ListNode.generate([1]), s.partition(ListNode.generate([1]), 0)) self.assertEqual(ListNode.generate([1, 2, 3]), s.partition(ListNode.generate([3, 1, 2]), 3))
def test_linked_list_cycle_ii(self): s = Solution() list1 = ListNode.generate([1, 2, 3, 4, 5, 6]) cycle_start = list1.find_by_value(3) list1.find_by_value(6).next = cycle_start self.assertTrue(cycle_start is s.detectCycle(list1)) self.assertEqual(None, s.detectCycle(ListNode.generate([1, 2, 3, 4, 5, 6]))) self.assertEqual(None, s.detectCycle(ListNode.generate([1]))) self.assertEqual(None, s.detectCycle(ListNode.generate([])))
def test_reverse_linked_list(self): s = Solution() self.assertEqual(ListNode.generate([]), s.reverseList(ListNode.generate([]))) self.assertEqual(ListNode.generate([5]), s.reverseList(ListNode.generate([5]))) self.assertEqual(ListNode.generate([5, 1]), s.reverseList(ListNode.generate([1, 5]))) self.assertEqual(ListNode.generate([3, 2, 1]), s.reverseList(ListNode.generate([1, 2, 3]))) self.assertEqual(ListNode.generate([5, 4, 3, 2, 1]), s.reverseList(ListNode.generate([1, 2, 3, 4, 5])))
def swapPairs(self, head: 'ListNode') -> 'ListNode': dummy = ListNode(0) dummy.next = head cur = dummy while cur.next and cur.next.next: # pre = cur.next # post = cur.next.next # cur.next, post.next, pre.next = post, pre, post.next cur.next.next.next, cur.next.next, cur.next = cur.next, cur.next.next.next, cur.next.next cur = cur.next.next # cur.next, cur.next.next.next, cur.next.next = cur.next.next, cur.next, cur.next.next.next # cur = cur.next.next return dummy.next
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode: dummy = ListNode(None) dummy.next = head f, b = dummy, dummy i = 0 while i < n: f = f.next i += 1 while f.next: f = f.next b = b.next b.next = b.next.next return dummy.next
def test_2_addTwoNumbers(self): l1 = ListNode(2) l1.next = ListNode(4) l1.next.next = ListNode(3) l2 = ListNode(5) l2.next = ListNode(6) l2.next.next = ListNode(4) l3 = self.solution._2_addTwoNumbers(l1, l2) self.assertEqual(7, l3.val) self.assertEqual(0, l3.next.val) self.assertEqual(8, l3.next.next.val)
def test4(self): nums = [1, 2, 3, 4, 5] dummy = ListNode() node = dummy for n in nums: next_node = ListNode(val=n) node.next = next_node node = next_node ans = Solution().rotateRight(head=dummy.next, k=10) expected = [1, 2, 3, 4, 5] actual = ans.vals_as_array() self.assertArrayEquals(expected=expected, actual=actual)
def removeNthFromEnd(self, head, n): dummy = ListNode(-1) dummy.next = head slow, fast = dummy, dummy for i in range(n): fast = fast.next while fast.next: slow, fast = slow.next, fast.next slow.next = slow.next.next return dummy.next
def deleteDuplicates1(self, head: ListNode) -> ListNode: # maintain a prev to indict last-previous node of current "while" prev = ListNode() prev.next = head # declare a res head real_head = ListNode() real_head.next = prev # side case if not head or not head.next: return head # maintain a flag to indict that if last while go in the "if head.val == head.next.val". flag = False while head.next: if head.val == head.next.val: head.next = head.next.next flag = True else: if flag: prev.next = head.next head = prev else: prev = head head = head.next flag = False return real_head.next.next
def toLinkedList(self, number): if number == 0: return ListNode(0) head = None node = None while number > 0: digit = number % 10 new = ListNode(digit) if head is None: head = new else: node.next = new node = new number = number // 10 return head
def partition(self, head: ListNode, x: int) -> ListNode: p1 = h1 = ListNode(None) p2 = h2 = ListNode(None) p = head while p: if p.val < x: p1.next = p p1 = p1.next else: p2.next = p p2 = p2.next p = p.next p1.next = h2.next p2.next = None return h1.next
def deleteDuplicates(self, head: ListNode) -> ListNode: if not head: return head dummy = ListNode(None) dummy.next = head p0, p1 = dummy, dummy.next.next while p1: if p1.val != p0.next.val: p0 = p0.next else: while p1 and p1.val == p0.next.val: p1 = p1.next p0.next = p1 p1 = p1.next if p1 else None return dummy.next
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: head = ListNode(None) r, h1, h2 = head, l1, l2 carry = 0 while h1 or h2 or carry: v1 = h1.val if h1 else 0 v2 = h2.val if h2 else 0 v = v1 + v2 + carry carry = v // 10 r.next = ListNode(v % 10) r = r.next h1 = h1.next if h1 else None h2 = h2.next if h2 else None return head.next