예제 #1
0
def delete_kth_last_node(ll: LinkedList, k: int) -> None:
    # case for head node removal
    if k == len(ll):
        temp = ll.head
        if len(ll) == 1:
            ll.head = None
            ll.rear = None
        else:
            ll.head = temp.next
            temp.next = None
        ll.length -= 1
        del temp
        return
    # generic node removal
    ptr_end = ll.head
    ptr_k = ll.head
    # moving the ptr_end up by k nodes
    for _ in range(k + 1):
        if ptr_end is None:
            raise ValueError(f"Linked list contains less than {k} nodes")
        ptr_end = ptr_end.next
    # searching for the end of the linked list
    # ptr_k is trailing the ptr_end up by k nodes, when end pointer reaches the end,
    # ptr_k is k nodes away from the end
    while ptr_end is not None:
        ptr_end = ptr_end.next
        ptr_k = ptr_k.next
    # removing the required element
    temp = ptr_k.next
    ptr_k.next = temp.next
    temp.next = None
    ll.length -= 1
    del temp
예제 #2
0
def sort(ll: LinkedList) -> LinkedList:
    ll.head = merge_sort(ll, ll.head)
    # reseting rear
    curr = ll.head
    while curr.next:
        curr = curr.next
    ll.rear = curr
    return ll
def rotate_linked_list(ll: LinkedList, k: int = 0) -> None:
    k = k % ll.length

    for _ in range(k):
        temp = ll.head
        ll.head = ll.head.next
        temp.next = None
        ll.rear.next = temp
        ll.rear = ll.rear.next
def reverse_inplace(ll: LinkedList) -> None:
    ll.rear = ll.head
    ptr_prev, ptr_curr, ptr_next = None, ll.head, ll.head.next
    # reversing the flow
    while ptr_curr is not None:
        ptr_curr.next = ptr_prev
        ptr_prev, ptr_curr = ptr_curr, ptr_next
        if ptr_next is None:
            break
        ptr_next = ptr_next.next
    ll.head = ptr_prev
def delete_zero_sum(linked_list: LinkedList) -> LinkedList:
    cumulative = 0
    cumulative_sum_map = {}
    dummy_head = Node(0)
    dummy_head.next = linked_list.head
    linked_list.head = dummy_head
    # removing 0 sum nodes using the property:
    # x -> y -> x [values (x and y) are cumulative sums] implies the linked list
    # contains x -> (y - x) -> -(y - x) and hence the nodes at the end can be removed
    # [this property can also be used to detect multiple nodes summing up to 0]
    node = linked_list.head
    while node:
        cumulative += node.val
        if cumulative in cumulative_sum_map:
            cumulative_sum_map[cumulative].next = node.next
        cumulative_sum_map[cumulative] = node
        node = node.next
    # resetting the linked list (removing dummy head and setting rear)
    linked_list.head = linked_list.head.next
    node = linked_list.head
    while node:
        linked_list.rear = node
        node = node.next
    return linked_list
예제 #6
0
def add_node_sorted(ll: LinkedList, val: int) -> None:
    ll.length += 1
    if not ll.head:
        ll.head = Node(val)
        ll.rear = ll.head
    elif val > ll.rear.val:
        ll.rear.next = Node(val)
        ll.rear = ll.rear.next
    else:
        pos = ll.head
        while pos.val < val:
            pos = pos.next
        temp = pos.val
        pos.val = val
        new_node = Node(temp)
        new_node.next = pos.next
        pos.next = new_node
        if pos == ll.rear:
            ll.rear = new_node
def clone(ll: LinkedList) -> LinkedList:
    clone_head = ll.head
    pos1 = ll.head
    pos2 = ll.head.next
    # duplicating all elements (by value in the linked list)
    # [a -> b -> c becomes a -> a -> b -> b -> c -> c]
    for _ in range(ll.length):
        pos1.next = Node(pos1.val)
        pos1 = pos1.next
        pos1.next = pos2
        pos1 = pos1.next
        if pos2 is None:
            break
        pos2 = pos2.next
    # setting the clone head to the proper position
    clone_head = clone_head.next
    pos1 = ll.head
    # setting the random pointer of the cloned linked list
    # (every 2nd element in the new linked list: a -> [a] -> b -> [b] -> c -> [c])
    for _ in range(ll.length - 1):
        pos1.next.random_ptr = pos1.random_ptr
        pos1 = pos1.next.next
    # reverting the linked list to its original form
    pos1 = ll.head
    pos2 = ll.head.next
    for _ in range(ll.length - 1):
        pos1.next = pos2.next
        pos2.next = pos2.next.next
        pos1 = pos1.next
        if pos2.next == None:
            break
        pos2 = pos2.next
    # creating the cloned linked list from the generated nodes
    cloned_LL = LinkedList()
    cloned_LL.head = clone_head
    cloned_LL.length = ll.length
    cloned_LL.rear = pos2
    return cloned_LL