ctci/02. Linked lists/2.5. sum_lists.md

4.0 KiB

2.5. Sum Lists

There are 2 numbers represented by a linked list, each node contains a single digit. The digits are stored in reverse order. Add the two numbers and return the sum as a linked list

  • Input: (7 --> 1 --> 6) + (5 --> 9 --> 2) == 617 + 295
  • Output: 2 --> 1 --> 9 == 912

First idea

I could do the sum directly over the list but it says pretty clearly that I have to add the two numbers, so I have to convert it into an int. Another question is, how do I know where/when one number starts and the other begins? Assume there's a node in the middle with value = 999.

public void LinkedListNode sum_lists(LinkedListNode node){
    int number = 0;
    int i = 0;
    Boolean which_num = False;
    while(node != null){
        if(node.data == 999){
            i = 0;
            node = node.next;
            which_num == True;
        }
        number += node.data * Math.pow(10, i);
        i += 1
        node = node.next;
    }

    // summed number to list
    LinkedListNode sum = null;
    LinkedListNode tmp = null;
    while (number > 0) {
        sum.data = number % 10;
        number = number / 10;
        tmp.next = sum;
        sum = tmp;
        tmp = null;
    }
    return sum;
}

Should work. O(n) time and O(1) space.

Follow up: Suppose the digits are stored in forward order. Adapt the algorithm

  • Input: (6 --> 1 --> 7) + (5 --> 9 --> 2) == 617 + 592
  • Output: 9 --> 1 --> 2 == 912
public void LinkedListNode sum_lists(LinkedListNode node){
    int number = 0;
    int i = 0;
    Boolean which_num = False;
    LinkedListNode head = node;
    while(node != null){
        if(node.data == 999){
            for(j = i; j >= 0; j--){
                number += head.data * Math.pow(10, i);
                head = head.next;
            }
            i = 0;
            head = head.next; // pointing at first digit of second num
            node = node.next;
            which_num == True;
            continue;
        }
        i += 1
        node = node.next;
    }

    // add second number
    for(j = i; j >= 0; j--){
        number += head.data * Math.pow(10, i);
        head = head.next;
    }

    // summed number to list
    LinkedListNode sum = null;
    while (number > 0) {
        sum.data = number % 10;
        number = number / 10;
        sum.next = null;
        sum = sum.next;
    }
    return sum;
}

A little more complicated but should work anyway. We can't add the number until we know how big it's going to be (either we reach 999 or the end of the list), then we iterate and add.

Hint 1

Converting the linked list into a number, adding and convert it back to a new linked list would get accepted, but you would be asked to do it without converting.

public void LinkedListNode sum_lists(LinkedListNode head){
    LinkedList head2 = head;
    while(head2.data != 999){
        head2 = head2.next;
    }
    // now we have to pointers, one to the first num, the other to the second
    // the numbers don't have to be the same 'length'...
    LinkedListNode sum = null;
    int i = 0;
    int extra = 0;
    int tmp = 0;
    while(head != null or head2 != null){
        if(head != null) tmp += head.data;
        if(head2 != null) tmp += head2.data;
        if(extra > 0){
            tmp += extra;
            extra = 0;
        }
        if(tmp > 9){
            extra = tmp & 10;
            tmp = tmp / 10;
        }
        sum.data = tmp * Math.pow(10, i);
        tmp = 0;
        sum.next = null;
        sum = sum.next;
    }
    return sum;
}

2 extra Nodes and 3 integers.

Hint 2

Try recursion. But I already do a loop, it's equivalent... right?

Hint 3

Make sure you consider that the input lists aren't of the same length.

Hint 4

Make sure you add the extra addition.

Forgot the last last one! Damn. Add this after the while

if (extra > 0){
    sum.next = null;
    sum.next.data = extra;
    sum = sum.next;
}

Solution

Code in the CTCI github repo.