LeetCode's second question: Add Two Numbers

Keywords: Programming

Question 2

1. Topic Requirements

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Given two non-empty linked lists to represent two non-negative integers. Bits are stored in reverse order, and each of their nodes only stores a single number. Add the two numbers back to a new linked list.

You can assume that neither of these numbers will begin with zero except the number 0.

2. Examples

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

3. My thoughts

First, the inverse list represents an integer, that is to say, the number in front of the list should be calculated first in normal calculation; the result is also a chain table in inverse order, so the result calculated first in normal calculation should appear in the result list first; this is a basic transformation from problem to solution; from this transformation we get. The data structure we need: first-visited link list nodes are computed first - first-in-first-out queues - first-in-first-out queues - first-in-first-out queues; first-in-first-out queues; first-in-first-out queues; and second-in-first-out queues.
Then there are several cases to be considered in calculation: the length of digits is not consistent, carry problem. As for the inconsistency of digit length, my method is divided into two parts: one is the sum of two operands, the other is the sum of one operand; carry problem is not very difficult to deal with, just need an intermediate variable record; one possible neglected problem is that when two digits are the same, carry occurs again. When you do, you need to add a 1 to the result. On this issue, my insight is that the first compilation failed because I forgot poll() in the second part of the processing, resulting in a dead loop; the second submission resulted in a wrong result, because at first I used the stack! Not a queue! This is because I did not really clarify the operation relationship here, and then usually use stacks more, a little thinking stereotype! After really calming down and thinking, I got the above ideas.
The code is as follows (49 ms):

	public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        	ArrayDeque<Integer> firstQueue=new ArrayDeque<>();
        	ArrayDeque<Integer> secondQueue=new ArrayDeque<>();
        	ArrayList<Integer> resultList=new ArrayList<>();
        	ArrayDeque<Integer> nextStack;
       		ListNode currentNode=l1;
        	while(currentNode!=null){
           		firstQueue.add(currentNode.val);
            		currentNode=currentNode.next;
        	}
        	currentNode=l2;
        	while(currentNode!=null){
            		secondQueue.add(currentNode.val);
            		currentNode=currentNode.next;
        	}
        	int carryBit=0;
        	int currentResult;
        	Integer firstNum,secondNum;
        	while((firstNum=firstQueue.peek())!=null&&(secondNum=secondQueue.peek())!=null){
            		currentResult=firstNum+secondNum+carryBit;
            		if(currentResult>=10){
                		currentResult-=10;
                		carryBit=1;
            		}else{
                		carryBit=0;
            		}
            		resultList.add(currentResult);
            		firstQueue.poll();
           		secondQueue.poll();
        	}
        	if(firstQueue.size()==0){
            		nextStack=secondQueue;
        	}else{
            		nextStack=firstQueue;
        	}
       		while((firstNum=nextStack.peek())!=null){
            		currentResult=firstNum+carryBit;
            		if(currentResult>=10){
                		currentResult-=10;
                		carryBit=1;
            		}else{
                		carryBit=0;
            		}
            		nextStack.poll();
            		resultList.add(currentResult);
        	}
        	if(carryBit==1){
            		resultList.add(1);
        	}
        	ListNode resultHead=new ListNode(-1);
        	ListNode currentTail=resultHead;
        	int length=resultList.size();
        	for(int i=0;i<length;i++){
            		currentTail.next=new ListNode(resultList.get(i));
            		currentTail=currentTail.next;
        	}
        	return resultHead.next;
    }

4. Solution of the Great Gods

	//35ms
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode result=null;
        ListNode index=null;
        int tmpTotal=0;
        boolean isFirst=true;
        boolean isAdd1=false;
        int l1val=0,l2val=0;
        while(l1!=null||l2!=null||isAdd1) {
            if(l1!=null) {
                l1val=l1.val;
                l1=l1.next;
            }
            if(l2!=null) {
                l2val=l2.val;
                l2=l2.next;
            }
            
            tmpTotal = (l1val+l2val);
            if(isAdd1) {
                tmpTotal++;
                isAdd1 = false;
            }
            if(tmpTotal>=10) {
                tmpTotal-=10;
                isAdd1=true;
            }
            ListNode tmp = new ListNode(tmpTotal);
            l1val=0;l2val=0;tmpTotal=0;
            if(isFirst) {
                result = tmp;
                index=result;
                isFirst=false;
                continue;
            }
            index.next = tmp;
            index=tmp;
            
        }
        return result;
    }
    
	//32ms
public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        //========== Pretreatment ensures that no nullpointer error can be calculated
        if(l1 == null){
            l1 = new ListNode(0);
        }
        if(l2 == null){
            l2 = new ListNode(0);
        }
        //========================================


         if(l1.next==null && l2.next==null){//Minimum case
             int val = l1.val+l2.val;
             if(val>9){
                 ListNode node = new ListNode(val%10);//Setting the second place
                 node.next = new ListNode(val/10);//Set the first place
                 return node;
             }else
             return new ListNode(val);
         }else {//Continuable iteration
             int val = l1.val+l2.val;
             if(val>9){
                 val = val-10;
                 if(l1.next!=null)  l1.next.val++;
                 else if(l2.next!=null)  l2.next.val++;
                 //Others//non-existent must be one of the two cases mentioned above.
             }

             ListNode node = new ListNode(val);
             //Start iteration
             node.next = addTwoNumbers(l1.next,l2.next);
             return node;
         }
}

32ms and 35ms have different solutions: one uses a while loop and the other uses recursion; but their common point is to establish a result list in the process of accessing the linked list; and I first put the linked list in the queue, then stored all the calculated result data in the linked list, and then traversed it again. Link lists generate result lists; thus it takes more time to insert and traverse links than the Gods'solution; this is because I "learned" the lesson from the previous problem and used data structures flexibly, resulting in "data structures" for the sake of "data structures". Now it seems that many of these actions can be handled when they are clearly accessible. It has to be put in a queue and processed, so it's 10 ms short. (Although the test may be inaccurate, stupidity is stupidity. It's a gap in thinking. ~There's nothing to say.)

In fact, there is a harvest! Clearly, the test cases are not empty in the title, but the Gods'code still detects this, I think, this is good programming habits!

Posted by willl on Thu, 18 Jul 2019 18:11:22 -0700