def test_solve(self):
        """Test solve

        Args:
            self: TestReverseLinkedListWithGroupSize

        Returns:
            None

        Raises:
            None
        """
        # Given
        elements_list = [1, 5, 7, 9, 15]
        input_list = LinkedList()
        for i in range(len(elements_list)):
            input_list.append(Node(elements_list[i]))

        reverse_linked_list_problem = ReverseLinkedListWithGroupSize(
            input_list, 3)

        # When
        output_list = reverse_linked_list_problem.solve()

        # Then
        self.assertEqual(output_list, [7, 5, 1, 9, 15])
    def test_solve(self):
        """Test solve

        Args:
            self: TestSwapNodesInPairs

        Returns:
            None

        Raises:
            None
        """
        # Given
        elements_list = [1, 5, 7, 9, 15]
        input_list = LinkedList()
        for i in range(len(elements_list)):
            input_list.append(Node(elements_list[i]))

        swap_nodes_problem = SwapNodesInPairs(input_list)

        # When
        output_list = swap_nodes_problem.solve()

        # Then
        self.assertEqual(output_list, [5, 1, 9, 7, 15])
    def test_solve_overflow(self):
        """Test solve (overflow)

        Args:
            self: AddTwoNumbers

        Returns:
            None

        Raises:
            None
        """
        # Given
        elements_list1 = [2, 4, 3]
        input_list1 = LinkedList()
        for i in range(len(elements_list1)):
            input_list1.append(Node(elements_list1[i]))

        elements_list2 = [5, 6, 4, 3]
        input_list2 = LinkedList()
        for i in range(len(elements_list2)):
            input_list2.append(Node(elements_list2[i]))

        add_two_numbers_problem = AddTwoNumbers(input_list1, input_list2)

        # When
        total = add_two_numbers_problem.solve()

        # Then
        self.assertEqual(total, [3, 8, 0, 7])
Ejemplo n.º 4
0
    def merge_two_sorted_linked_lists(node1, node2):
        """Merge K Sorted Linked Lists Divide and Conquer

        Args:
            node1: First node
            node2: Second node

        Returns:
            Node

        Raises:
            None
        """
        merged_list = LinkedList()

        # iterate over both the lists and append the smallest
        while node1 is not None and node2 is not None:
            if node1.data < node2.data:
                merged_list.append(Node(node1.data))
                node1 = node1.next_node
            else:
                merged_list.append(Node(node2.data))
                node2 = node2.next_node

        # append the remaining elements from the second list
        if node1 is None:
            while node2 is not None:
                merged_list.append(Node(node2.data))
                node2 = node2.next_node

        # append the remaining elements from the first list
        if node2 is None:
            while node1 is not None:
                merged_list.append(Node(node1.data))
                node1 = node1.next_node

        return merged_list.head
    def solve(self):
        """Solve the problem

        Note: O(n) (runtime) solution works by simultaneously iterating over both the list and taking the carry to the digit.

        Args:

        Returns:
            list

        Raises:
            None
        """
        print("Solving {} problem ...".format(self.PROBLEM_NAME))

        node1 = self.input_linked_list1.head
        node2 = self.input_linked_list2.head

        carry = 0
        sum_list = LinkedList()
        while node1 is not None and node2 is not None:
            digit1 = node1.data
            digit2 = node2.data

            digit_sum = digit1 + digit2 + carry

            if digit_sum > 9:
                carry = 1
            else:
                carry = 0

            sum_list.append(Node(digit_sum % 10))

            node1 = node1.next_node
            node2 = node2.next_node

        node = None
        if node1 is None and node2 is not None:
            node = node2
        elif node1 is not None and node2 is None:
            node = node1

        while node is not None:
            digit_sum = node.data + carry
            if digit_sum > 9:
                carry = 1
            sum_list.append(Node(digit_sum % 10))
            node = node.next_node

        return list(reversed(sum_list.output_list()))
Ejemplo n.º 6
0
    def __init__(self, hash_table_size=DEFAULT_HASH_TABLE_SIZE):
        """Init

        Args:
            hash_table_size: Hash table size

        Returns:
            None

        Raises:
            None
        """
        super().__init__()
        self.hash_table_size = hash_table_size
        self.buckets = [LinkedList() for _ in range(hash_table_size)]
        self.keys = {}
Ejemplo n.º 7
0
    def test_construct(self):
        """Test for construct

        Args:
            self: TestLinkedList

        Returns:
            None

        Raises:
            None
        """
        # Given
        input_linked_list = LinkedList()
        input_linked_list.append(Node(1))
        input_linked_list.append(Node(2))
        input_linked_list.append(Node(3))
        input_linked_list.append(Node(4))
        input_linked_list.append(Node(5))

        # Then
        self.assertEqual(input_linked_list.output_list(), [1, 2, 3, 4, 5])
Ejemplo n.º 8
0
    def test_solve(self):
        """Test solve

        Args:
            self: TestCopyListWithRandomPointer

        Returns:
            None

        Raises:
            None
        """
        # Given
        input_linked_list = LinkedList()
        input_linked_list.append(Node(1))
        input_linked_list.append(Node(2))
        input_linked_list.append(Node(3))
        input_linked_list.append(Node(4))
        input_linked_list.append(Node(5))

        # 1's random points to 3
        input_linked_list.head.random = input_linked_list.head.next_node.next_node

        # 2's random points to 1
        input_linked_list.head.next_node.random = input_linked_list.head

        # 3's random points to 5
        input_linked_list.head.next_node.next_node.random = input_linked_list.head.next_node.next_node.next_node.next_node

        # 4's random points to 5
        input_linked_list.head.next_node.next_node.next_node.random = input_linked_list.head.next_node.next_node.next_node.next_node

        # 5's random points to 2
        input_linked_list.head.next_node.next_node.next_node.next_node.random = input_linked_list.head.next_node

        copy_list_with_random_pointer_problem = CopyListWithRandomPointer(input_linked_list)

        # When
        output_list = copy_list_with_random_pointer_problem.solve()

        # Then
        self.assertEqual(output_list, [1, 2, 3, 4, 5])
Ejemplo n.º 9
0
    def solve(self):
        """Solve the problem

        Note: O(n) (runtime) and O(1) (space) solution works by:
             i.   Inserting a clone node between two nodes.
             ii.  Updating the random pointer of the cloned nodes.
             iii. Detaching original and cloned nodes.

        Args:

        Returns:
            list

        Raises:
            None
        """
        print("Solving {} problem ...".format(self.PROBLEM_NAME))

        # i. Insert cloned node between two nodes for all the nodes
        current_node = self.input_linked_list.head
        while current_node is not None:
            next_node = current_node.next_node
            new_node = Node(current_node.data)
            current_node.next_node = new_node
            new_node.next_node = next_node
            current_node = next_node

        # ii. Update the random pointer of the cloned node using the random pointer's clone of the original node.
        current_node = self.input_linked_list.head
        while current_node is not None:
            new_node = current_node.next_node
            new_node.random = current_node.random.next_node
            current_node = current_node.next_node.next_node

        # iii. Detach original and cloned nodes
        current_node = self.input_linked_list.head
        cloned_node = current_node.next_node
        while current_node is not None:
            tmp = current_node.next_node
            if current_node.next_node is not None:
                current_node.next_node = current_node.next_node.next_node
            current_node = tmp

        return LinkedList(cloned_node).output_list()
Ejemplo n.º 10
0
    def solve(self):
        """Solve the problem
        Note:
            i. Brute force solution would work by comparing two lists at a time for k times. The total runtime complexity would be O(nk^2)
            = 2n + 3n + 4n + ... + kn = n(k(k+1)/2 -1). The solution will only require a constant space O(1).

           ii. Heap has a complexity of O(log k) to order based on the heap property. We could maintain a heap of size k with smallest element from each list.
           After removing a element from the list, the next element is placed in the heap. With nk elements, the overall runtime complexity is O(nk logk) and
           a space complexity of O(k).

           iii. Divide and conquer works by merging two different lists at the same time (begin and end), and finally merging two combined lists.
           Compared to brute force with k merges O(nk^2), the runtime complexity is O(nk logk) and the space complexity of O(1).
        Args:

        Returns:
            list

        Raises:
            None
        """
        print("Solving {} problem ...".format(self.PROBLEM_NAME))

        if len(self.input_linked_lists_list) == 0:
            return []

        input_linked_lists_list = []
        for k in range(len(self.input_linked_lists_list)):
            input_linked_lists_list.append(
                self.input_linked_lists_list[k].head)

        end = len(self.input_linked_lists_list) - 1

        while end > 0:
            begin = 0
            while begin < end:
                input_linked_lists_list[
                    begin] = self.merge_two_sorted_linked_lists(
                        input_linked_lists_list[begin],
                        input_linked_lists_list[end])
                begin = begin + 1
                end = end - 1

        return LinkedList(input_linked_lists_list[0]).output_list()
Ejemplo n.º 11
0
    def test_solve(self):
        """Test solve

        Args:
            self: MergeKSortedLinkedListsPriorityQueue

        Returns:
            None

        Raises:
            None
        """
        # Given
        elements_list1 = [1, 5, 7, 9, 15, 17]
        input_list1 = LinkedList()
        for i in range(len(elements_list1)):
            input_list1.append(Node(elements_list1[i]))

        elements_list2 = [2, 3, 3, 6]
        input_list2 = LinkedList()
        for i in range(len(elements_list2)):
            input_list2.append(Node(elements_list2[i]))

        elements_list3 = [4, 6, 8, 10, 12, 14, 16, 18]
        input_list3 = LinkedList()
        for i in range(len(elements_list3)):
            input_list3.append(Node(elements_list3[i]))

        input_linked_lists_list = [input_list1, input_list2, input_list3]

        merge_k_linked_lists_problem = MergeKSortedLinkedListsPriorityQueue(input_linked_lists_list)

        # When
        output_list = merge_k_linked_lists_problem.solve()

        # Then
        self.assertEqual(output_list, [1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18])
Ejemplo n.º 12
0
    def test_reverse(self):
        """Test for reverse

        Args:
            self: TestLinkedList

        Returns:
            None

        Raises:
            None
        """
        # Given
        input_linked_list = LinkedList()
        input_linked_list.append(Node(1))
        input_linked_list.append(Node(2))
        input_linked_list.append(Node(3))
        input_linked_list.append(Node(4))
        input_linked_list.append(Node(5))

        # When
        input_linked_list.reverse()

        # Then
        self.assertEqual(input_linked_list.output_list(), [5, 4, 3, 2, 1])
Ejemplo n.º 13
0
    def solve(self):
        """Solve the problem

        Note: O(n) (runtime) and O(1) (space) solution works by iterating over both the linked lists
              and appending the smallest one to the merged_list.

        Args:

        Returns:
            list

        Raises:
            None
        """
        print("Solving {} problem ...".format(self.PROBLEM_NAME))

        merged_list = LinkedList()

        node1 = self.input_linked_list1.head
        node2 = self.input_linked_list2.head

        # iterate over both the lists and append the smallest
        while node1 is not None and node2 is not None:
            if node1.data < node2.data:
                merged_list.append(Node(node1.data))
                node1 = node1.next_node
            else:
                merged_list.append(Node(node2.data))
                node2 = node2.next_node

        # append the remaining elements from the second list
        if node1 is None:
            while node2 is not None:
                merged_list.append(Node(node2.data))
                node2 = node2.next_node

        # append the remaining elements from the first list
        if node2 is None:
            while node1 is not None:
                merged_list.append(Node(node1.data))
                node1 = node1.next_node

        return merged_list.output_list()