len_h2 -= 1 # advance prev_head by 1 prev_head = prev_head.next # if len_h1 > 0, it means len_h2 == 0 # append the rest of h1 (and remember h2 and the rest of the list is linked to h1) if len_h1 > 0: prev_head.next = h1 # otherwise len_h2 must > 0 else: prev_head.next = h2 # now we have completed the merge part, advance the prev_head to the last number of the merged list # one of len_h1 and len_h2 must be positive, reduce to 0 while len_h1 > 0 or len_h2 > 0: prev_head = prev_head.next len_h1 -= 1 len_h2 -= 1 # this is the most important line, it connect the last element of the merged list to the next group # we have updated head to be the first element of the next group (if any) # thus we can avoid of having an infinite loop (since h1 and h2 are linked all the way to the end) # we are essentially skipping the repeating part (where the loop will arise) and move on to the next group prev_head.next = head return return_head test = list2ListNode([4, 5, 10, 2, 3, 6, 7, 9]) print(ListNode2list(sortList_bottom_up(test)))
# put curr to the less_list else: if not l_head: l_head = curr l_last = curr else: assert (l_last is not None) l_last.next = curr l_last = curr # advance curr by one step curr = curr.next # if the greater_list is not empty if g_head: # cut whatever is behind the tail of the greater_list g_last.next = None # if the less_list is not empty, append it to the left of the greater_list if l_head: l_last.next = g_head return l_head # otherwise there is no nodes less than x in the linked list else: return g_head test = list2ListNode([1, 4, 3, 2, 5, 2]) test_x = 3 print(ListNode2list(partition(test, test_x)))
if slow.next == fast: slow = fast else: slow.next = fast.next fast = fast.next return dummy.next # 递归 # Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: if head is None or head.next is None: return head if head.next and head.val == head.next.val: while head.next != None and head.val == head.next.val: head = head.next return self.deleteDuplicates(head.next) else: head.next = self.deleteDuplicates(head.next) return head # 读写指针 list2ListNode([1, 2, 3, 3, 4, 4, 5])
# Priority queue is a queue with priority, and instead of first in first out, # the element with highest priority (minimum priority number) will be retrieved first # doing this allows us retrieve the node with the smallest value with O(logk), # but insertion can also take O(logk) # without priority queue, we can use the method in the first solution, find min node in a loop O(k) head = ListNode(-1) prev_node = head q = PriorityQueue() for ln in lists: if ln: # wrapper here and below to prevent priority queue from comparing listnodes with the same priority q.put(PrioritizedItem(ln.val, ln)) # OR use q.put(Wrapper(ln)) while not q.empty(): node = q.get().item # OR use node = q.get().node prev_node.next = node prev_node = node if node.next: q.put(PrioritizedItem(node.next.val, node.next)) # OR use q.put(Wrapper(node.next)) return head.next test_list = [[1, 4, 5], [1, 3, 4], [2, 6]] # test_list = [[],[]] test = [list2ListNode(in_ln) for in_ln in test_list] print(ListNode2list(mergeKLists_priority_queue(test)))
while l1_stack or l2_stack: if len(l1_stack) == 0: l1_val, l2_val = 0, l2_stack.pop() elif len(l2_stack) == 0: l1_val, l2_val = l1_stack.pop(), 0 else: l1_val, l2_val = l1_stack.pop(), l2_stack.pop() curr_sum = l1_val + l2_val + addone curr_node = ListNode(curr_sum % 10) curr_node.next = head head = curr_node if curr_sum >= 10: addone = 1 else: addone = 0 if addone == 1: new_head = ListNode(1) new_head.next = head return new_head else: return head test_1 = list2ListNode([2]) test_2 = list2ListNode([8]) print(ListNode2list(addTwoNumbers(test_1, test_2)))
stack.append(curr_node) curr_node = curr_node.next # the one added the latest is the new head group_head = stack.pop() prev_node = group_head # save the next group next_group = group_head.next # loop until stack is empty while stack: curr_node = stack.pop() prev_node.next = curr_node prev_node = curr_node # now curr_node is the tail of the group (whose next is still the penultimate node, therefore a loop) # to break the loop, reset the next to next_group, note that cannot reset to None # since if this is the final group, then curr_node.next should point to the remaining nodes in the list curr_node.next = next_group # similar as above if i == 0: prev_tail = curr_node return_head = group_head else: prev_tail.next = group_head prev_tail = curr_node # similarly, update group tail to the next group curr_node = next_group return return_head test = list2ListNode([1, 2, 3, 4, 5, 6, 7, 8, 9]) print(ListNode2list(reverseKGroup_stack(test, 3)))
slow = fast = head while slow and fast and fast.next: slow = slow.next fast = fast.next.next # next find the head of the second half if fast: # the length of the list is odd, slow.next is the head of the second half second_head = slow.next else: # the length of the list is even, slow is the head of the second half second_head = slow # reverse the second half reversed_second_head = reverse_list(second_head) # compare the reversed second half with the whole list # (note that we are only comparing the first half of the whole list though) # After comparing all nodes in the reversed second half, head should be either # 1) at the head of the second half (even list) # 2) one node before the second half (odd list) while reversed_second_head: if head.val == reversed_second_head.val: head = head.next reversed_second_head = reversed_second_head.next else: return False return True test = list2ListNode([1]) print(isPalindrome(test))
from utils import list2ListNode, ListNode2list, ListNode def removeElements(head, val): """ Linear search with pseudo head Time: O(n) Space: O(1) """ if not head: return head prev_node = return_head = ListNode(-1) return_head.next = head while head: if head.val == val: prev_node.next = head.next head = head.next else: prev_node = head head = head.next return return_head.next test = list2ListNode([1, 2, 6, 3, 4, 5, 6]) print(ListNode2list(removeElements(test, 6)))
# if curr_node is already larger than the last of the sorted node (prev_node) # then we don't need to move curr_node, simply increment the sorted list by one node if curr_node.val >= prev_node.val: prev_node = curr_node curr_node = curr_node.next continue # otherwise, curr_node is not immediately sorted as above # take curr_node out of the list prev_node.next = curr_node.next # insert curr_node to the sorted part by scanning from the start p = return_head while p.next.val <= curr_node.val: p = p.next # stop until p.val < curr_node.val < p.next.val # insert curr_node between p and p.next curr_node.next = p.next p.next = curr_node # get the next unsorted node curr_node = prev_node.next return return_head.next test = list2ListNode([1, 5, 3, 4, 0]) print( ListNode2list( insertionSortList(test) ) )
# link prev (even) to the next node (even), thus removing curr from its original position prev.next = next_node # link the whole even list after curr (odd) curr.next = first_eve # link curr to the end of the odd list last_odd.next = curr # two possibilities at the end of the list # 1) next_node is None (the whole list has odd number of nodes) # then break from the loop and we are done # which means curr (before we have processed it) is the last element of the whole list # 2) next_node is the last node in the list (the whole list has even number of nodes) # enter the if block but curr will be updated to None # which means the loop will stop as well if next_node: # curr is now the last node in the odd list last_odd = curr # go to the next ODD node (remember next_node is always even) curr = next_node.next # update prev (even) prev = next_node else: break return head test = list2ListNode([1, 2, 3, 4, 5, 6, 7]) print(ListNode2list(oddEvenList(test)))
from utils import list2ListNode, ListNode2list, ListNode def deleteDuplicates(head): """ Delete neighbouring nodes with the same value Time: O(n) Space: O(1) """ if not head: return head return_head = ListNode(-1) return_head.next = head # loop invariant: # All nodes in the list up to the pointer head do not contain duplicate elements. while head.next: if head.next.val == head.val: head.next = head.next.next else: head = head.next return return_head.next test = list2ListNode([1, 1, 2, 3]) print(ListNode2list(deleteDuplicates(test)))
# keep advance right pointer until the gap from the first node is n elif i < n: i += 1 # if the last node is to be removed if n == 1: left.next = None # if the i did not reach n before right pointer hit the last node # then n is greater or equal to the length (L) of the list # and since n is a valid number, it must be L # remove the first node elif i < n: return head.next # normal cases, note here left.next is the node we want to remove else: left.next = left.next.next return head # test = [1,2,3,4,5] # n= 2 # test = [1,2] # n = 2 test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] n = 7 test_ln = list2ListNode(test) print(test) print(ListNode2list(removeNthFromEnd_two_pointers(test_ln, n)))
left = head # cut the link of the first half to the second half slow.next = None # pseudo head to store the merged list, head will be the next node to return_head return_head = ListNode(-1) curr = return_head # merge the two lists, in every iteration, first link the left to the merged list then the right while left and right: left_next = left.next right_next = right.next # link first the left then the right curr.next = left curr.next.next = right # update the end of the merged list curr = right # move forward left and right left = left_next right = right_next # if right is still not empty if right: curr.next = right # else left is still not empty else: curr.next = left test = list2ListNode([1, 2, 3, 4, 5]) reorderList(test) print(ListNode2list(test))