Exemple #1
0
    def test__align__long_list2(self):
        d1 = ListNode.of([1])
        d2 = ListNode.of([1, 2, 3])
        (res1, res2) = SumLists()._align(d1, d2)

        self.assertEqual("0,0,1", str(res1))
        self.assertEqual("1,2,3", str(res2))
Exemple #2
0
    def test_is_palindrome(self):
        res = PalindromeLinkedList().isPalindrome(ListNode(1, ListNode(2)))
        self.assertFalse(res)

        res = PalindromeLinkedList().isPalindrome(
            ListNode(1, ListNode(2, ListNode(1))))
        self.assertTrue(res)
 def delete_middle(middle: ListNode):
     """
     Solution: copy data and next ref from next node to given.
     It does not work for the last node
     """
     next_node = middle.next
     middle.next = next_node.next
     middle.val = next_node.val
Exemple #4
0
 def test_add_two_numbers(self):
     """
     Example:
     Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
     Output: 7 -> 8 -> 0 -> 7
     """
     res = AddTwoNumbers2().addTwoNumbers(ListNode.of([7, 2, 4, 3]),
                                          ListNode.of([5, 6, 4]))
     self.assertEqual("7,8,0,7", str(res))
Exemple #5
0
    def test_sum_of_reversed_with_carry(self):
        d1 = ListNode.of([9])
        d2 = ListNode.of([1])
        res = SumLists().sum_of_reversed(d1, d2).str_with_tail()
        self.assertEqual("0,1", res)

        d1 = ListNode.of([9, 9, 9])
        d2 = ListNode.of([5])
        res = SumLists().sum_of_reversed(d1, d2).str_with_tail()
        self.assertEqual("4,0,0,1", res)
    def test_merge_two_lists__same_len(self):
        # Init
        l1 = ListNode.of([1, 3, 5])
        l2 = ListNode.of([2, 4, 6])

        # Call and check
        l3 = self.alg.mergeTwoLists(l1, l2).str_with_tail()
        self.assertEqual('1,2,3,4,5,6', l3)

        l3 = self.alg.mergeTwoLists(l2, l1).str_with_tail()
        self.assertEqual('1,2,3,4,5,6', l3)
    def test_merge_two_lists__one_empty(self):
        # Init
        l1 = ListNode.of([])
        l2 = ListNode.of([1, 3, 4, 10])
        # Call and check
        l3 = self.alg.mergeTwoLists(l1, l2).str_with_tail()
        self.assertEqual('1,3,4,10', l3)

        l2 = ListNode.of([])
        l1 = ListNode.of([1, 3, 4, 10])
        # Call and check
        l3 = self.alg.mergeTwoLists(l1, l2).str_with_tail()
        self.assertEqual('1,3,4,10', l3)
Exemple #8
0
    def _traverse(self, node: TreeNode, level):
        """
        Traverse node's children adding them to hash map by level
        """
        if node is None:
            return

        if level not in self._heads:
            # First node of this level, create linked list
            self._heads[level] = self._tails[level] = ListNode(node.val, None)
        else:
            # Add this node to the tail of this level
            self._tails[level].next = ListNode(node.val, None)
            self._tails[level] = self._tails[level].next

        self._traverse(node.left, level + 1)
        self._traverse(node.right, level + 1)
Exemple #9
0
    def _adjust_nodes(self, l1: ListNode,
                      l2: ListNode) -> (ListNode, ListNode):
        """ Add leading zeroes to a smaller list """
        l1len, l2len = self._list_len(l1), self._list_len(l2)
        if l1len == l2len:
            return l1, l2

        zroot = ListNode(0)
        znode = ztail = zroot
        for i in range(0, abs(l1len - l2len)):
            ztail = znode
            znode.next = znode = ListNode(0)

        if l1len < l2len:
            ztail.next, l1 = l1, zroot
        else:
            ztail.next, l2 = l2, zroot
        return l1, l2
Exemple #10
0
    def sum(self, head1: ListNode, head2: ListNode):
        """
        Sum of two numbers, represented by linked lists in direct order
        Idea: alight the lists, go from left to right, store sum from 0 to 18 without carry, sum list is reversed
        Then go through sum list from right to left, calculating sum from 0 to 9 using carry, reversing the list
        As a result we have sum list from left to right
        """
        head1, head2 = self._align(head1, head2)
        node1, node2 = head1, head2
        head_res = node_sum = node_sum_left = None

        # Calc reversed sum list, numbers from 0 to 18 without carry
        while node1 is not None and node2 is not None:
            node_sum = ListNode(node1.val + node2.val, node_sum_left)
            # First step
            if head_res is None:
                head_res = node_sum
            # Step right
            node_sum_left = node_sum
            node1 = node1.next
            node2 = node2.next

        # Apply carry, reverse sum list
        carry: int = 0
        node_sum_left = node_sum.next
        node_sum.next = None
        while node_sum_left is not None:
            # Apply carry
            carry = (node_sum.val + carry) // 10
            node_sum.val = (node_sum.val + carry) % 10
            # Reverse the node
            new_left = node_sum_left.next
            node_sum_left.next = node_sum
            node_sum = node_sum_left
            node_sum_left = new_left

        # If carry, add new head
        node_sum.val += carry
        carry = node_sum.val // 10
        node_sum.val %= 10
        if carry > 0:
            head_res = ListNode(1, node_sum)

        return head_res
Exemple #11
0
    def _add_with_hold(self, l1: ListNode, l2: ListNode):
        """Sum considering hold from recursive rest"""
        if not l1:
            return None, 0
        # Recursively add the rest of the list considering hold
        nextnode, nexthold = self._add_with_hold(l1.next, l2.next)

        summ = (l1.val + l2.val + nexthold)
        node, hold = ListNode(summ % 10, nextnode), summ // 10
        return node, hold
Exemple #12
0
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        Recursive approach
        """

        # Addjust the length with leading zeroes
        l1, l2 = self._adjust_nodes(l1, l2)

        node, hold = self._add_with_hold(l1, l2)
        root = ListNode(1, node) if hold else node
        return root
Exemple #13
0
 def test_reverse_between__example1(self):
     """
     Example:
     Input: 1->2->3->4->5->NULL, m = 2, n = 4
     Output: 1->4->3->2->5->NULL
     """
     res = ReverseLinkedList2().reverseBetween(head=ListNode.of(
         [1, 2, 3, 4, 5]),
                                               m=2,
                                               n=4)
     self.assertEqual("1,4,3,2,5", str(res))
Exemple #14
0
    def sum_of_reversed(head1: ListNode, head2: ListNode):
        """
        Sum of two numbers, represented by linked lists in reverse order
        """
        node1 = head1
        node2 = head2
        # Sum
        head_res = None
        prev_node_res = None
        carry = 0

        while node1 is not None \
                or node2 is not None:
            val1 = node1.val if node1 is not None else 0
            val2 = node2.val if node2 is not None else 0

            s = val1 + val2 + carry
            # Calc carry
            if s >= 10:
                carry = 1
                s %= 10
            else:
                carry = 0

            # Calc sum and add to a new node
            if prev_node_res is not None:
                newnode3 = ListNode(s, None)
                prev_node_res.next = newnode3
                prev_node_res = newnode3
            else:
                # Initial step
                prev_node_res = head_res = ListNode(s, None)
            node1 = node1.next if node1 is not None else None
            node2 = node2.next if node2 is not None else None

        # Process remained carry if needed
        if carry > 0:
            prev_node_res.next = ListNode(carry, None)

        return head_res
Exemple #15
0
    def _align(head1: ListNode, head2: ListNode):
        """
        Left pad smaller linked lists with zeroes to make sizes equal
        :return: aligned_head1, aligned_head2
        """
        node1 = head1
        node2 = head2
        # Go to the tail of list1 or list2
        while node1.next is not None and node2.next is not None:
            node1 = node1.next
            node2 = node2.next

        if node1.next is None and node2.next is None:
            # If lists are of equal size, no align
            return head1, head2

        # Go to the tail of longer list and calculate delta size
        (longer_head,
         longer_node) = (head1, node1) if node1.next is not None else (head2,
                                                                       node2)
        pad_head = None
        pad_node = None
        while longer_node.next is not None:
            if pad_head is None:
                # First
                pad_head = pad_node = ListNode(0, None)
            else:
                # Add next node to pad list
                pad_node.next = ListNode(0, None)
                pad_node = pad_node.next
            longer_node = longer_node.next

        # Insert paddings  before the head of shorter list
        pad_node.next = head2 if longer_head == head1 else head1

        return (pad_head, head2) if longer_head == head2 else (head1, pad_head)
Exemple #16
0
 def as_linked_list(arr):
     """
     Converts array of values to linked list
     :param arr: array of values
     :return: head node of linked list
     """
     if arr is None or len(arr) == 0:
         return None
     head = None
     last_node = None
     for value in arr:
         node = ListNode(value, None)
         if head is None:
             # First node
             head = node
             last_node = node
         else:
             # Middle or last node
             last_node.next = node
             last_node = node
     return head
Exemple #17
0
    def test_sum__with_diff_size(self):
        d1 = ListNode.of([1])
        d2 = ListNode.of([3, 2, 1])
        res = SumLists().sum(d1, d2).str_with_tail()

        self.assertEqual("3,2,2", res)
Exemple #18
0
 def test_align__empty(self):
     d1 = ListNode.of([1])
     d2 = ListNode.of([2])
     (res1, res2) = SumLists()._align(d1, d2)
     self.assertEqual("1", str(res1))
     self.assertEqual("2", str(res2))
Exemple #19
0
 def test_add_two_numbers_999_1(self):
     res = AddTwoNumbers2().addTwoNumbers(ListNode.of([9, 9, 9]),
                                          ListNode.of([1]))
     self.assertEqual("1,0,0,0", str(res))
Exemple #20
0
 def test_getlen(self):
     l = PalindromeLinkedList().getlen(ListNode(1, ListNode(2)))
     self.assertEqual(2, l)
Exemple #21
0
 def test_reverse(self):
     n = PalindromeLinkedList().reverse(ListNode(1, ListNode(2)))
     self.assertEqual(2, n.val)
     self.assertEqual(1, n.next.val)
Exemple #22
0
 def test_reverse_between__emptyleft(self):
     res = ReverseLinkedList2().reverseBetween(head=ListNode.of(
         [1, 2, 3, 4, 5]),
                                               m=1,
                                               n=2)
     self.assertEqual("2,1,3,4,5", str(res))
Exemple #23
0
    def test_sum_of_reversed__with_carry(self):
        d1 = ListNode.of([3])
        d2 = ListNode.of([9])
        res = SumLists().sum_of_reversed(d1, d2).str_with_tail()

        self.assertEqual("2,1", res)
Exemple #24
0
    def test_sum_of_reversed(self):
        d1 = ListNode.of([3, 2, 1])
        d2 = ListNode.of([3, 2, 1])
        res = SumLists().sum_of_reversed(d1, d2).str_with_tail()

        self.assertEqual("6,4,2", res)
Exemple #25
0
 def test_reverse_between__emptyright(self):
     res = ReverseLinkedList2().reverseBetween(head=ListNode.of(
         [1, 2, 3, 4, 5]),
                                               m=4,
                                               n=5)
     self.assertEqual("1,2,3,5,4", str(res))
Exemple #26
0
    def test_sum__with_equal_size(self):
        d1 = ListNode.of([3, 2, 1])
        d2 = ListNode.of([3, 2, 1])
        res = SumLists().sum_of_reversed(d1, d2)

        self.assertEqual("6,4,2", str(res))
Exemple #27
0
 def test_reverse_single(self):
     n = PalindromeLinkedList().reverse(ListNode(1))
     self.assertEqual(1, n.val)
Exemple #28
0
 def test_reverse_between__12345_5_5(self):
     res = ReverseLinkedList2().reverseBetween(head=ListNode.of(
         [1, 2, 3, 4, 5]),
                                               m=5,
                                               n=5)
     self.assertEqual("1,2,3,4,5", str(res))
Exemple #29
0
 def test_is_palindrome_single(self):
     res = PalindromeLinkedList().isPalindrome(ListNode(1))
     self.assertTrue(res)
Exemple #30
0
 def test_reverse_between__15(self):
     res = ReverseLinkedList2().reverseBetween(head=ListNode.of([1]),
                                               m=1,
                                               n=1)
     self.assertEqual("1", str(res))