Search code examples
linked-listsingly-linked-list

Issue in carryovers while adding two numbers in a linked list


I'm solving the leetcode question for adding two numbers in a linked list.

The following is my code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* node1 = l1;
        ListNode* node2 = l2;

        if(!node1 && !node2){
            return l1;
        }
        if(!node1){
            return l2;
        }
        if(!node2){
            return l1;
        }
        while(node1 && node2){
                node1->val = node1->val + node2->val;
                node1 = node1->next;
                node2 = node2->next;    
        }
        if(!node1 && !node2){
            return l1;
        }
        if(!node2){
            node1 = node1->next;
        }
        if(!node1){
            node1 = node2;
        }
        node1 = l1;
        if(!node1){
            return l1;
        }
        while(l1->next != nullptr){
            if(l1->val >9){
                l1->next->val += (l1->val)/10;
                l1->val = l1->val%10;
            }
            l1 = l1->next;
        }
        ListNode* abc = new ListNode();
        if(l1->next == nullptr && l1->val>9){
            l1->next = abc;
            abc->val = (l1->val)/10;
            l1->val = l1->val%10;

        }
        return node1;
    }
};

When the testcase value for l1 is [8,8,8] and l2 is [2,2], I get [0,1,9] which is the correct and expected result but if I modify the test cases to [8,8,6] and [2,2,2], I get the sum as [10,10,8]. Similarly, I am getting the wrong answer for l1 = [2,4,3] and l2 = [5,6,4] but I cannot figure out why.


Solution

  • There are a few issues:

    • Right after the first loop you have this code:

          if(!node1 && !node2){
              return l1;
          }
      

      But if that return gets executed, you haven't checked whether any of the node values overflowed. So you might end up with some nodes having 10 or more as value. So this code block has to be removed.

    • The next two if blocks are not accomplishing anything:

          if(!node2){
              node1 = node1->next;
          }
          if(!node1){
              node1 = node2;
          }
      

      They were intended to attach the remainder of the longest list to the l1 list, but these assignments are only assigning to variables; they are not changing any pointer in the linked list. To do that, you need to know what the previous node was, so you can update its next field. But you don't have a reference to the preceding node anymore... To solve that, make sure to exit the first loop one step earlier, so that both node1 and node2 are not yet nullptr, but one of them is the tail node of the list they are in.

    • After having done node1 = l1, you check whether node1 is nullptr, but that will never be true, since you checked that at the top of the function.

    • Not a problem, but in this statement:

      if(l1->next == nullptr && l1->val>9){
      

      ...the first condition is guaranteed to be true, so you can reduce this code to:

      if(l1->val>9){
      

    More comments can be made about your code, but here is the version that tackles the above mentioned points:

    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode* node1 = l1;
            ListNode* node2 = l2;
            if(!node1 && !node2){
                return l1;
            }
            while (node1->next && node2->next){ // Stop when arriving at a tail node
                node1->val = node1->val + node2->val;
                node1 = node1->next;
                node2 = node2->next;    
            }
            node1->val = node1->val + node2->val; // Also update that node
            if(!node1->next){ // If the first list is the shortest
                node1->next = node2->next; // then attach the remaining nodes to it
            }
            node1 = l1;
            while(l1->next != nullptr){
                if(l1->val >9){
                    l1->next->val += (l1->val)/10;
                    l1->val = l1->val%10;
                }
                l1 = l1->next;
            }
            ListNode* abc = new ListNode();
            if(l1->val>9){
                l1->next = abc;
                abc->val = (l1->val)/10;
                l1->val = l1->val%10;
            }
            return node1;
        }
    };
    

    A next improvement would be to do join the two loops into one loop, so that you process the carry immediately when storing the sum.