def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: l1_vals = [] l2_vals = [] while l1 is not None: l1_vals.append(l1.val) l1 = l1.next while l2 is not None: l2_vals.append(l2.val) l2 = l2.next head = curr = None carry = 0 while len(l1_vals) != 0 or len(l2_vals) != 0: num = carry num += (l1_vals.pop() if len(l1_vals) != 0 else 0) num += (l2_vals.pop() if len(l2_vals) != 0 else 0) carry = num // 10 num %= 10 head = ListNode(num) head.next = curr curr = head if carry == 1: head = ListNode(carry) head.next = curr return head
def addTwoNumbers(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ stack1 = [] while l1: stack1.append(l1.val) l1 = l1.next stack2 = [] while l2: stack2.append(l2.val) l2 = l2.next next_value = 0 new_head = None v_head = None while stack1 or stack2: value1 = stack1.pop() if stack1 else 0 value2 = stack2.pop() if stack2 else 0 v_head = ListNode((value1 + value2 + next_value) % 10) v_head.next = new_head new_head = v_head next_value = (value1 + value2 + next_value) // 10 if next_value: v_head = ListNode(next_value) v_head.next = new_head new_head = v_head return v_head
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: if l1 is None: return l2 elif l2 is None: return l1 elif l1.val < l2.val: l1.next = self.mergeTwoLists(l1.next, l2) return l1 else: l2.next = self.mergeTwoLists(l1, l2.next) return l2
def reorderList(self, head: ListNode) -> None: """ Do not return anything, modify head in-place instead. """ head_node1 = ListNode() head_node1.next = head slow = head_node1 fast = head_node1 while fast is not None: fast = fast.next if fast is None: break fast = fast.next slow = slow.next head_node2 = ListNode() head_node2.next = slow.next slow.next = None #LinkedListUtil.showList(head_node1) #LinkedListUtil.showList(head_node2) rev_head_node = ListNode() rev_ptr = head_node2.next while rev_ptr is not None: last_next_node = rev_head_node.next rev_head_node.next = rev_ptr rev_ptr = rev_ptr.next rev_head_node.next.next = last_next_node merged_head_node = ListNode() merge_ptr1 = rev_head_node.next merge_ptr0 = head_node1.next merged_ptr = merged_head_node turn_flag = True while merge_ptr0 is not None and merge_ptr1 is not None: if turn_flag: merged_ptr.next = merge_ptr0 merge_ptr0 = merge_ptr0.next else: merged_ptr.next = merge_ptr1 merge_ptr1 = merge_ptr1.next merged_ptr = merged_ptr.next turn_flag = not turn_flag if merge_ptr0 is not None: merged_ptr.next = merge_ptr0 merged_ptr = merged_ptr.next elif merge_ptr1 is not None: merged_ptr.next = merge_ptr1 merged_ptr = merged_ptr.next return merged_head_node
def _swap_children(self, x0: ListNode, y0: ListNode): """ Swap `x0.next` and `y0.next`""" x1, y1 = x0.next, y0.next if y0 == x1: x0.next = y1 x1.next = y1.next y1.next = x1 else: x0.next = y1 y0.next = x1 x1.next, y1.next = y1.next, x1.next return x1
def remove_nth_from_end(head, n): """ Remove the n-th node from the end of list :param head: head node of given linked list :type head: ListNode :param n: order n :type n: int :return: head node of operated linked list :rtype: ListNode """ # basic case if head is None: return head # initialize variables dummy = ListNode(None) dummy.next = head slow = fast = dummy # slow pointer is slower than fast pointer by n positions count = 0 while fast.next is not None: fast = fast.next count += 1 if count > n: slow = slow.next # if need to remove node if count >= n: tmp = slow.next slow.next = slow.next.next del tmp return dummy.next
def sort_list(head): def partition(start, end): node = start.next.next # node to iterate first_pivot = start.next first_pivot.next = end # Insert large node between pivot and end last_pivot = first_pivot while node != end: tmp = node.next if node.val > first_pivot.val: node.next = last_pivot.next last_pivot.next = node elif node.val < first_pivot.val: node.next = start.next start.next = node else: node.next = last_pivot.next last_pivot.next = node last_pivot = last_pivot.next node = tmp return [first_pivot, last_pivot] def qsort(start, end): if start.next != end: first_pivot, last_pivot = partition(start, end) qsort(start, first_pivot) qsort(last_pivot, end) head_pre = ListNode(0) head_pre.next = head qsort(head_pre, None) return head_pre.next
def swap_pairs(head): """ Swap every two adjacent nodes in given linked list :param head: head node of given linked list :type head: ListNode :return: head node of swapped linked list :rtype: ListNode """ # basic case if head is None: return head # dummy head dummy = ListNode(None) dummy.next = head # swap pairs curr = dummy while curr.next is not None and curr.next.next is not None: tmp_next = curr.next tmp_nnnext = curr.next.next.next curr.next = curr.next.next curr.next.next = tmp_next curr.next.next.next = tmp_nnnext curr = curr.next.next return dummy.next
def addTwoNumbers(self, l1, l2): n = l1.val + l2.val l3 = ListNode(n % 10) l3.next = ListNode(n // 10) p1 = l1.next p2 = l2.next p3 = l3 while True: if p1 and p2: sum = p1.val + p2.val + p3.next.val p3.next.val = sum % 10 p3.next.next = ListNode(sum // 10) p1 = p1.next p2 = p2.next p3 = p3.next elif p1 and not p2: sum = p1.val + p3.next.val p3.next.val = sum % 10 p3.next.next = ListNode(sum // 10) p1 = p1.next p3 = p3.next elif not p1 and p2: sum = p2.val + p3.next.val p3.next.val = sum % 10 p3.next.next = ListNode(sum // 10) p2 = p2.next p3 = p3.next else: if p3.next.val == 0: p3.next = None break return l3
def swapPairs_loop(head): """ Loop Time: O(n) (but in runtime slower than recursion) Space: O(1) (but in runtime similar to recursion) """ # dummy head for return start = ListNode(-1) start.next = head # var to contain the previous node prev_node = start # stop the loop if only one or zero node left while head and head.next: # the current two nodes to be swapped first_node = head second_node = head.next # swap, and linked the second node in the pair to the previous node prev_node.next = second_node first_node.next = second_node.next second_node.next = first_node # update previous node to the next pair # update head to the first node in the next pair prev_node = first_node head = first_node.next return start.next
def reverseBetween(self, head, m, n): """ :type head: ListNode :type m: int :type n: int :rtype: ListNode """ dummy = ListNode(-1) dummy.next = head pre = dummy # 找到翻转链表部分的前一个节点, 1->2->3->4->5->NULL, m = 2, n = 4 指的是 节点值为1 for _ in range(m - 1): pre = pre.next # 用双指针,进行链表翻转 node = None cur = pre.next for _ in range(n - m + 1): tmp = cur.next cur.next = node node = cur cur = tmp # 将翻转部分 和 原链表拼接 pre.next.next = cur pre.next = node 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 index is greater than the length, # the node will not be inserted. if index > self.size: return # [so weird] If index is negative, # the node will be inserted at the head of the list. if index < 0: index = 0 self.size += 1 # find predecessor of the node to be added pred = self.head for _ in range(index): pred = pred.next # node to be added to_add = ListNode(val) # insertion itself to_add.next = pred.next pred.next = to_add
def remove_elements(head, val): """ Remove all elements from a linked list of integers that have value val. :param head: head node of given linked list :type head: ListNode :param val: value to remove :type val: int :return: head node of removed linked list :rtype: ListNode """ # basic case if head is None: return head # dummy head dummy = ListNode(None) dummy.next = head # traverse to remove nodes with given value curr = dummy while curr is not None: while curr.next is not None and curr.next.val == val: tmp = curr.next curr.next = curr.next.next del tmp curr = curr.next return dummy.next
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: carry = 0 out = None currNode = None while not (l1 is None and l2 is None and carry == 0): currVal = 0 if l1 is not None: currVal += l1.val if l2 is not None: currVal += l2.val if carry == 1: currVal += 1 carry = 0 if currVal >= 10: carry = 1 currVal -= 10 if out is None: currNode = ListNode(currVal) out = currNode else: currNode.next = ListNode(currVal) currNode = currNode.next if l1: l1 = l1.next if l2: l2 = l2.next return out
def insertion_sort_list(head): """ Sort a linked list by insertion sort :param head: head node of given linked list :type head: ListNode :return: head node of sorted linked list :rtype: ListNode """ dummy = ListNode(None) dummy.next = head curr = head while curr is not None: if curr.next is not None and curr.next.val < curr.val: # find insertion position pre = dummy while pre.next is not None and pre.next.val < curr.next.val: pre = pre.next # insert the next node of curr to the position after node pre tmp = pre.next pre.next = curr.next curr.next = curr.next.next pre.next.next = tmp else: curr = curr.next return dummy.next
def delete_duplicates(head): """ Remove all duplicates in given linked list, leaving only distinct numbers :param head: head node of given linked list :type head: ListNode :return: head node of operated linked list :rtype: ListNode """ if head is None: return head dummy_head = ListNode(None) dummy_head.next = head curr = dummy_head while curr.next is not None and curr.next.next is not None: if curr.next.val == curr.next.next.val: val = curr.next.val while curr.next is not None and curr.next.val == val: tmp = curr.next curr.next = curr.next.next del tmp else: curr = curr.next return dummy_head.next
def deleteDuplicates_last(head): """ Remove all duplicates but the last and finally itself Time: O(n) Space: O(1) """ if not head: return head # setup the pseudo head return_head = ListNode(-1) return_head.next = head # prev_node is last the non-duplicate node prev_node = return_head # head could be None here while head and head.next: if head.val == head.next.val: # keep on moving forward until head is now the last occurrence while head.next and head.val == head.next.val: head = head.next # skip the last occurrence, NOTE: the new head could be None head = head.next prev_node.next = head else: prev_node = head head = head.next return return_head.next
def mergeTwoLists(l1, l2): """ Straight forward merge Time: O(m+n), m = len(l1), n = len(l2) Space: O(1) """ # Assignment such as a = l1 (l1 is a ListNode) # will assign the address to start, change of a's `next` or `val` will result in change in l1's `next` or `val` # because the changes were made to the object stored in the common address # similarly if two assignments were made of the same variable: a, b =l1, l1 # then change of a's `next` or `val` will result in change in b's and l1's # If reassign a to another ListNode say l2, a = l2, then change of a will not affect that of b and l1 # Summary: Changing an object's properties through one of its assigned variable will change the object itself and # all the other assigned variables curr = ListNode(-1) # auxiliary head pointer to retrieve the whole list start = curr while l1 is not None or l2 is not None: # if one of them is empty and then append the other to the end of the result and return if l1 is None: curr.next = l2 return start.next elif l2 is None: curr.next = l1 return start.next # if both are non-empty if l1.val < l2.val: # below will append all nodes of l1 to curr, `start` will change at the same time # e.g. curr = [3, 5], l1 = [4, 6], l2 = [5], start = [-1, 1, 2, 3, 5] # then after the execution, curr = [3, 4, 6], start = [-1, 1, 2, 3, 4, 6] curr.next = l1 # below will advance l1 by 1 node # following the above example, after execution, l1 = [6] l1 = l1.next # below will advance curr by 1 node, and has no effect on `start` # since curr will be assigned to a new ListNode (curr.next) # and no changes were made to existing nodes # following the above example, after execution, curr = [4, 6], l1 = [6], l2 = [5] # in the next iteration, enter l2.val < l1.val and curr will be [4, 5]... curr = curr.next else: curr.next = l2 l2 = l2.next curr = curr.next return start.next
def reverseN(self, head: ListNode, n) -> ListNode: if n == 1: self.successor = head.next return head last = self.reverseN(head.next, n - 1) head.next.next = head head.next = self.successor return last
def insert(pre, cur, val): nonlocal res new_node = ListNode(val) if not pre: res = new_node else: pre.next = new_node new_node.next = cur
def reverseKGroup(self, head, k): """ :type head: ListNode :type k: int :rtype: ListNode """ head_node = ListNode(0) head_node.next = head
def reverseK(head_node, k): dummpy_node = ListNode(0) dummpy_node.next = head_node tmp_ptr = dummpy_node for i in range(k): tmp_ptr = tmp_ptr.next if i < k - 1 and tmp_ptr is None: return dummpy_node.next
def checkHasCycle(): # test_list1 = [3, 2, 0, -4] # test_list2 = [1, 2] # test_list3 = [1] test_link1_1 = ListNode(3) test_link1_2 = ListNode(2) test_link1_3 = ListNode(0) test_link1_4 = ListNode(-4) test_link1_1.next = test_link1_2 test_link1_2.next = test_link1_3 test_link1_3.next = test_link1_4 test_link1_4.next = test_link1_2 test_link2_1 = ListNode(1) test_link2_2 = ListNode(2) test_link2_1.next = test_link2_2 test_link2_2.next = test_link2_1 test_link3_1 = ListNode(1) test_link3_1.next = None print(Solution.hasCycle1(test_link1_1)) print(Solution.hasCycle1(test_link2_1)) print(Solution.hasCycle1(test_link3_1)) print(Solution.hasCycle2(test_link1_1)) print(Solution.hasCycle2(test_link2_1)) print(Solution.hasCycle2(test_link3_1))
def detectCycle(): # test_list1 = [3, 2, 0, -4] # test_list2 = [1, 2] # test_list3 = [1] test_link1_1 = ListNode(3) test_link1_2 = ListNode(2) test_link1_3 = ListNode(0) test_link1_4 = ListNode(-4) test_link1_1.next = test_link1_2 test_link1_2.next = test_link1_3 test_link1_3.next = test_link1_4 test_link1_4.next = test_link1_2 test_link2_1 = ListNode(1) test_link2_2 = ListNode(2) test_link2_1.next = test_link2_2 test_link2_2.next = test_link2_1 test_link3_1 = ListNode(1) test_link3_1.next = None with exec_time(): print(Solution.detectCycle1(test_link1_1)) print(Solution.detectCycle1(test_link2_1)) print(Solution.detectCycle1(test_link3_1)) with exec_time(): print(Solution.detectCycle2(test_link1_1)) print(Solution.detectCycle2(test_link2_1)) print(Solution.detectCycle2(test_link3_1))
def get_intersection_node(): ln1 = ListNode(1) ln2 = ListNode(2) ln3 = ListNode(3) ln4 = ListNode(4) ln1.next = ln2 ln2.next = ln3 ln3.next = ln4 ln4.next = None ln5 = ListNode(5) ln6 = ListNode(6) ln5.next = ln6 ln7 = ListNode(7) ln7.next = ln2 ln8 = ListNode(8) ln8.next = ln6 res = [Solution.getIntersectionNode(ln1, ln5), Solution.getIntersectionNode(ln1, ln7), Solution.getIntersectionNode(ln1, ln8), Solution.getIntersectionNode(ln5, ln7), Solution.getIntersectionNode(ln5, ln8)] for i in res: if i is None: print("the intersection node value is None") continue print("the intersection node value is {}".format(i.val))
def removeElements(self, head, val): prev = ListNode(0) prev.next = head cur = prev while cur.next: if cur.next.val == val: cur.next = cur.next.next else: cur = cur.next return prev.next
def copy(raw): if raw in cache: return cache[raw] new = Node(raw.val) cache[raw] = new if raw.next: new.next = copy(raw.next) if raw.random: new.random = copy(raw.random) return new
def addTwoNumbers(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ def get_len(l): count = 0 while l is not None: l = l.next count += 1 return count def helper(l1, l2, offset): if l1 is None: return None if offset == 0: result = ListNode(l1.val + l2.val) post = helper(l1.next, l2.next, 0) else: result = ListNode(l1.val) post = helper(l1.next, l2, offset-1) if post is not None and post.val > 9: result.val += 1 post.val -= 10 result.next = post return result size1 = get_len(l1) size2 = get_len(l2) head = ListNode(1) if size1 < size2: head.next = helper(l2, l1, size2 - size1) else: head.next = helper(l1, l2, size1 - size2) if head.next.val > 9: head.next.val -= 10 return head else: return head.next
def reverseKGroup(self, head: ListNode, k: int) -> ListNode: pre_head = ListNode(None) pre_head.next = head pre_node = pre_head last_node = self._move(pre_node, k) while last_node: next_k = last_node.next pre_node = self._reverse_sub_list_node(pre_node, next_k, k) last_node = self._move(next_k, k - 1) return pre_head.next
def reverseBetween(head, m, n): """ Iterative reversing with multiple pointers Time: O(n) Space: O(1) """ if not head: return head count = 1 return_head = ListNode(-1) return_head.next = head # start points to the node before the reversed part (i.e. m-1 th node in the list) start = return_head # prev points to the head of the reversed part # last points to the end of the reversed part prev = last = head # curr points to the node we are currently looking at curr = head.next while curr: # if we have not reached the part that needs to be reversed if count < m: # start is one step before last while count < m, but will fix once count >= m # before getting into the need-to-reverse part, last and start point to the same node # curr is one step ahead of last last = last.next start = start.next prev = prev.next curr = curr.next # the elif statement will run only if n > m elif m <= count <= n - 1: # get next_node, this will be curr in the next step next_node = curr.next # connect the next to the end of the reversed part last.next = next_node # prev always points to the head of the reversed part # append the reversed part to curr curr.next = prev # curr is now the new head of the reversed part start.next = curr # update prev and curr to be consistent with their definitions prev = curr curr = next_node # else we are outside the part that needs to be reversed else: break count += 1 return return_head.next
def deleteDuplicates(self, head: ListNode) -> ListNode: tmp = head if head is None or head.next is None: return head while True: if head.next is None: return tmp if head.val == head.next.val: head.next = head.next.next else: head = head.next
def helper(l1, l2, offset): if l1 is None: return None if offset == 0: result = ListNode(l1.val + l2.val) post = helper(l1.next, l2.next, 0) else: result = ListNode(l1.val) post = helper(l1.next, l2, offset-1) if post is not None and post.val > 9: result.val += 1 post.val -= 10 result.next = post return result
def merge_sort(self, head, n): # non recursive def split(p, step): last = None for i in xrange(step): if p is None: break last = p p = p.next if last: last.next = None return p def merge(h1, h2, tail): p1, p2 = h1, h2 while p1 or p2: if not p2 or p1 and p1.val <= p2.val: tail.next = p1 tail = p1 p1 = p1.next elif not p1 or p2 and p2.val <= p1.val: tail.next = p2 tail = p2 p2 = p2.next else: break return tail dummy = ListNode(0) dummy.next = head left = right = tail = None step = 1 while step < n: p = dummy.next tail = dummy while p: left = p right = split(p, step) p = split(right, step) tail = merge(left, right, tail) step <<= 1 return dummy.next
def swapPairs(self, head): """ :type head: ListNode :rtype: ListNode """ if head is None: return head fake_head = ListNode(0) fake_head.next = head p,q,r = fake_head,head,head.next while q and r: p.next = r q.next = r.next r.next = q p = q q = p.next r = q.next if q else None return fake_head.next
return node lA, lB = link_len(headA), link_len(headB) if lA > lB: hA, hB = link_index(headA, lA - lB), headB elif lA < lB: hA, hB = headA, link_index(headB, lB - lA) else: hA, hB = headA, headB nA, nB = hA, hB while nA and nB: if nA == nB: return nA nA = nA.next nB = nB.next return None if __name__ == '__main__': headC = ListNode.build_linked_list([4,5,6]) headA = ListNode(1) headA.next = ListNode(2) headA.next.next = headC headB = headC print Solution().getIntersectionNode(headA, headB) print Solution().getIntersectionNode(None, None) print Solution().getIntersectionNode(ListNode.build_linked_list([1,3,5,7,9,11,13,15,17,19,21]), ListNode.build_linked_list([2]))