Example #1
0
def add_lists(lst1, lst2):
    h1 = lst1.head
    h2 = lst2.head

    ans = LinkedList()

    carry = 0

    while h1 or h2:
        if not h1:
            result = h2.data + carry
            h1 = h1.next

        elif not h2:
            result = h1.data + carry
            h2 = h2.next

        else:
            result = h1.data + h2.data + carry
            h1 = h1.next
            h2 = h2.next

        carry = 1 if result >= 10 else 0

        ans.append_to_tail(result - carry * 10)

    return ans
Example #2
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
Example #3
0
    def test1(self):
        lst = LinkedList(1, 2, 3, 3, 4)

        required = LinkedList(1, 2, 3, 4)

        remove_duplicate_nodes(lst)

        self.assertEqual(lst, required)
Example #4
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
Example #5
0
    def test4(self):
        lst1 = LinkedList(3, 1, 5)
        lst2 = LinkedList(5, 9, 2)

        required = LinkedList(8, 0, 8)

        ans = add_lists(lst1, lst2)

        self.assertEqual(ans, required)
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
Example #7
0
    def test3(self):
        lst = LinkedList(1, 1, 3, 1, 1)

        n = lst.get_node(3)

        remove_node_from_middle(n)

        required = LinkedList(1, 1, 1, 1)

        self.assertEqual(lst, required)
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
Example #9
0
    def test5(self):
        lst = LinkedList(1, 2, 3, 4, 5)

        n = lst.get_node(3)

        lst.get_node(5).next = n

        self.assertEqual(is_circular(lst), True)

        lst1 = LinkedList(1, 2, 3, 4)

        self.assertEqual(is_circular(lst1), False)
Example #10
0
    def __init__(self, hashTableSize=defaultHashTableSize):

        # Should probably be named HashTableEntry. You get the point.
        self.buckets = [LinkedList() for x in range(0, hashTableSize)]

        # A quick lookup for has() and getKeys().
        self.keys = {}
Example #11
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
Example #12
0
def add_linked_lists(ll1: LinkedList, ll2: LinkedList) -> LinkedList:
    sum_linked_list = LinkedList()
    pos1, pos2 = ll1.head, ll2.head
    carry, curr_position_sum = 0, 0
    # generating the sum of the linked lists
    while pos1 or pos2:
        if pos1 == None:
            curr_position_sum = pos2.val + carry
            if curr_position_sum >= 10:
                carry, curr_position_sum = 1, curr_position_sum - 10
            else:
                carry = 0
        elif pos2 == None:
            curr_position_sum = pos1.val + carry
            if curr_position_sum >= 10:
                carry, curr_position_sum = 1, curr_position_sum - 10
            else:
                carry = 0
        else:
            curr_position_sum = pos2.val + pos1.val + carry
            if curr_position_sum >= 10:
                carry, curr_position_sum = 1, curr_position_sum - 10
            else:
                carry = 0
        sum_linked_list.add(curr_position_sum)
        # moving to the next value
        if pos1:
            pos1 = pos1.next
        if pos2:
            pos2 = pos2.next
    if carry == 1:
        sum_linked_list.add(1)
    return sum_linked_list
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
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
def merge_sorted_linked_list(list_of_LL: List[LinkedList]) -> LinkedList:
    k = len(list_of_LL)
    position_arr = [LL.head for LL in list_of_LL]
    sorted_ll = LinkedList()
    while any(position_arr):
        # finding the node with minimum value
        minimum = maxsize
        for i in range(k):
            if position_arr[i] is not None:
                if position_arr[i].val < minimum:
                    minimum = position_arr[i].val
                    position = i
        # generating new node
        if sorted_ll.head is None:
            sorted_ll.add(position_arr[position].val)
            curr_position = sorted_ll.head
        else:
            curr_position.next = Node(position_arr[position].val)
            curr_position = curr_position.next
        sorted_ll.length += 1
        position_arr[position] = position_arr[position].next
    # resetting rear
    sorted_ll.rear = curr_position
    return sorted_ll
Example #16
0
 def testNewLinkedList(self):
     self.new_list = LinkedList()
     assert self.new_list.head == None
        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


if __name__ == "__main__":
    linked_list = LinkedList()
    for elem in [3, 4, -7, 5, -6, 6]:
        linked_list.add(elem)
    print(delete_zero_sum(linked_list))

    linked_list = LinkedList()
    for elem in [7, 4, -4, -7, 5, -6, 6]:
        linked_list.add(elem)
    print(delete_zero_sum(linked_list))

    linked_list = LinkedList()
    for elem in [7, 4, -4, -7, 5, -6, 6, 10]:
        linked_list.add(elem)
    print(delete_zero_sum(linked_list))
"""
SPECS:
Example #18
0

def swap_nodes(ll: LinkedList) -> Node:
    node1 = ll.head
    node2 = ll.head.next
    while True:
        try:
            node1.val, node2.val = node2.val, node1.val
            node1, node2 = node1.next.next, node2.next.next
        except:
            break
    return ll.head


if __name__ == "__main__":
    LL = LinkedList()

    LL.add(1)
    LL.add(2)
    LL.add(3)
    LL.add(4)

    print(LL)
    print(swap_nodes(LL))
"""
SPECS:

TIME COMPLEXITY: O(n)
SPACE COMPLEXITY: O(1)
"""
def rearrange(ll: LinkedList) -> None:
    nodes_count = len(ll)
    nodes = [int(node) for node in ll]
    nodes.sort()

    for i in range(2, nodes_count, 2):
        nodes[i], nodes[i - 1] = nodes[i - 1], nodes[i]

    curr = ll.head
    for i in range(nodes_count):
        curr.val = nodes[i]
        curr = curr.next


if __name__ == "__main__":
    LL = LinkedList()

    for i in range(1, 6):
        LL.add(i)

    print(LL)
    rearrange(LL)
    print(LL)
"""
SPECS:

TIME COMPLEXITY: O(n)
SPACE COMPLEXITY: O(n)
"""
Example #20
0
        fast = fast.next.next
    return slow


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


if __name__ == "__main__":
    LL = LinkedList()

    for val in [6, 3, 7, 5, 30, 2, 50]:
        LL.add(val)

    print(LL)
    sort(LL)
    print(LL)
    print()

    LL = LinkedList()

    for val in [4, 1, -3, 99]:
        LL.add(val)

    print(LL)
Example #21
0
    length = len(ll)
    if length in (0, 1):
        return ll

    for _ in range(length):
        pos1, pos2 = randint(0, length - 1), randint(0, length - 1)
        node1, node2 = ll.head, ll.head
        for _ in range(pos1):
            node1 = node1.next
        for _ in range(pos2):
            node2 = node2.next
        node1.val, node2.val = node2.val, node1.val
    return ll


if __name__ == "__main__":
    ll = LinkedList()

    for i in range(1, 6):
        ll.add(i)

    print(ll)
    shuffle(ll)
    print(ll)
"""
SPECS:

TIME COMPLEXITY: O(n ^ 2)
SPACE COMPLEXITY: O(1)
"""
 def setup_class(self):
     print("Linked list tests")
     self.makeLinkedList = lambda self, initial_data=None: LinkedList(
         initial_data)
Example #23
0
 def __init__(self) -> None:
     self.List = LinkedList()
     self.start = None
     self.end = None
Example #24
0
    def test2(self):
        lst = LinkedList(1, 1, 3, 1, 1)

        self.assertEqual(find_nth(lst, 3), 3)
Example #25
0
def create_linked_list(val: int) -> LinkedList:
    LL = LinkedList()
    while val > 0:
        LL.add(val % 10)
        val = val // 10
    return LL
        # generating new node
        if sorted_ll.head is None:
            sorted_ll.add(position_arr[position].val)
            curr_position = sorted_ll.head
        else:
            curr_position.next = Node(position_arr[position].val)
            curr_position = curr_position.next
        sorted_ll.length += 1
        position_arr[position] = position_arr[position].next
    # resetting rear
    sorted_ll.rear = curr_position
    return sorted_ll


if __name__ == "__main__":
    LL1 = LinkedList()
    LL1.add(2)
    LL1.add(25)
    LL1.add(70)

    LL2 = LinkedList()
    LL2.add(5)
    LL2.add(8)
    LL2.add(14)
    LL2.add(15)
    LL2.add(21)
    LL2.add(48)

    LL3 = LinkedList()
    LL3.add(0)
    LL3.add(90)
Example #27
0
from DataStructures.LinkedList import LinkedList
from DataStructures.Element import Element

# Test cases
# Set up some Elements
e1 = Element(1)
e2 = Element(2)
e3 = Element(3)
e4 = Element(4)

# Start setting up a LinkedList
ll = LinkedList(e1)
ll.append(e2)

ll.append(e3)

# Test get_position
# Should print 3
print(ll.head.next.next.value)
# Should also print 3
print(ll.get_position(3).value)

# Test insert
ll.insert(e4, 3)
# Should print 4 now
print(ll.get_position(3).value)

# Test delete
ll.delete(1)
# Should print 2 now
print(ll.get_position(1).value)
Example #28
0
class TestLinkedList:
    new_list = LinkedList()

    def testNewLinkedList(self):
        self.new_list = LinkedList()
        assert self.new_list.head == None

    def testAddNode(self):
        self.new_list.addNode('node_1')
        assert self.new_list.head.data == 'node_1'

    def testGetLength(self):
        size = self.new_list.length()
        assert size == 1
        self.new_list.addNode('node_2')
        size = self.new_list.length()
        assert size == 2
        self.new_list.addNode('node_3')
        self.new_list.addNode('node_4')

    def testStr(self):
        print(self.new_list)

    def testDelOldestNode(self):
        node = self.new_list.delOldestNode()
        assert self.new_list.length() == 3
        assert node == 'node_1'

    def testDelNewestNode(self):
        node = self.new_list.delNewestNode()
        assert self.new_list.length() == 2
        assert node == 'node_4'
Example #29
0
import sys
sys.path.append("../")

from DataStructures.LinkedList import LinkedList,Element

try:
	print("Start LinkedList Tests ..")
	
	# Set up some Elements
	e1 = Element(1)
	e2 = Element(2)
	e3 = Element(3)
	e4 = Element(4)

	# Start setting up a LinkedList
	ll = LinkedList(e1)
	ll.append(e2)
	ll.append(e3)

	# Test cases
	
	# Should print 3
	assert ll.head.next.next.value == 3

	# Test get_position
	# Should print 3
	assert ll.get_position(3).value == 3

	# Test insert
	ll.insert(e4,3)
	# Should print 4 now
        elif len1 > len2:
            pos = len1 - len2
            for _ in range(pos):
                pos1 = pos1.next
        # checking for intersecting node
        for _ in range(smaller_len):
            if pos1 is pos2:
                return pos1
            pos1 = pos1.next
            pos2 = pos2.next
    # no intersection
    return None


if __name__ == "__main__":
    ll1 = LinkedList()
    ll1.add(5)
    ll1.add(6)
    ll1.add(7)
    ll1.add(8)

    ll2 = LinkedList()
    ll2.add(1)
    ll2.add(2)
    ll2.add(3)
    ll2.add(4)

    ll3 = LinkedList()
    ll3.add(9)
    ll3.rear.next = ll1.head.next.next
    ll3.rear = ll3.rear.next.next
def distribute(a_list, val):
    c = LinkedList()
    #print('distribute ', a_list, "| val ", val)
    for elem in a_list:
        c.append(val + elem.data)
    return c