当前位置 博文首页 > Add Two Numbers_让代码改变世界:LeetCode 2

    Add Two Numbers_让代码改变世界:LeetCode 2

    作者:[db:作者] 时间:2021-07-10 22:17

    这是LeetCode第二题,难度和第一题一样,也是Medium(中等)。

    原题:

    You are given two linked lists representing two non-negative numbers. 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.

    Input:?(2 -> 4 -> 3) + (5 -> 6 -> 4)
    Output:?7 -> 0 -> 8

    题目是将存放在链表中的两个整数的相加,链表每一个节点放的是一位带权的数字。

    这其实是用链表“模拟”计算机中的整数相加的过程,理解上面并没有什么难度,实现上也比较容易。一般思路是取出各位依次相加,在这过程中要注意保留进位位。主要考察点应该在对链表的操作上面,我就是因为对链表操作不太熟悉,所以走了很多弯路,不过最终结果还是不错的,成绩为44ms,虽然在C++中属于中等偏下,但这毕竟只是开始,希望以后越做越好吧

    本人的源代码:

    <span style="font-size:14px;">class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode* lhs=l1;//左操作数
    		ListNode* rhs=l2;//又操作数
    		ListNode* tempNode=new ListNode(0);
    		ListNode* sum=tempNode;//和
    		ListNode* pSum=sum;
    		int cf=0;//进位标识为
    		while(lhs!=NULL && rhs!=NULL){
    			int tempSum=lhs->val+rhs->val+cf;
    			ListNode* tempNode=new ListNode(tempSum%10);
    			pSum->next=tempNode;
    			if(tempSum-10>=0) {cf=1;}
    			else {cf=0;}
    			lhs=lhs->next;
    			rhs=rhs->next;
    			pSum=pSum->next;
    			
    		}
    		while(lhs!=NULL){
    			int tempSum=lhs->val+cf;
    			ListNode* tempNode=new ListNode(tempSum%10);
    			pSum->next=tempNode;
    			if(tempSum-10>=0) cf=1;
    			else cf=0;
    			lhs=lhs->next;
    			pSum=pSum->next;
    		}
    		while(rhs!=NULL){
    			int tempSum=rhs->val+cf;
    			ListNode* tempNode=new ListNode(tempSum%10);
    			pSum->next=tempNode;
    			if(tempSum-10>=0) cf=1;
    			else cf=0;
    			rhs=rhs->next;
    			pSum=pSum->next;
    		}
    		if(cf==1){
    			ListNode* tempNode=new ListNode(1);
    			pSum->next=tempNode;
    		}
    		return sum->next;
    
        }
    };</span>
    这里面逻辑关系比较简单,就是取出两个链表的每一位相加,然后存放到目标链表中,同时注意保存符号位,至于怎么得到相加结果的十位和个位就是一些固定的小技巧了。具体在编码过程中要注意返回类型为指针类型,这里容易陷入返回局部变量指针的“不归路”。也就是说,是不能将一个个临时的ListNode对象连在一起返回的,这样会造成致命的错误!正确的方法是使用动态内存分配,使在局部作用域中定义的变量可以跳出局部变量的作用域。当然这同时增加了内存泄露的风险。这一点对使用该方法的用户增添了负担,是一个改进的方向。

    代码虽然容易理解,但明显冗余度较大,所以又找了一个大神的精简代码,作为参考

    大神代码:

    <span style="font-size:14px;">class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode preheader(-1), *curr=&preheader;
            int carry=0;
            while(l1||l2||carry) {
                curr->next = new ListNode(((l1?l1->val:0)+(l2?l2->val:0)+carry)%10);
                curr = curr->next;
                carry = ((l1?l1->val:0)+(l2?l2->val:0)+carry)/10;
                l1?l1=l1->next:0;
                l2?l2=l2->next:0;
            }
            return preheader.next;
        }
    };</span>
    这两段代码的算法思想是一致的,所以效率并没有明显差异。下面的代码为36ms。(其实还是比较大的,有20%呢)。这个代码也没有什么难理解的,就是把三种情况全部综合在一起了,利用很多三元操作符来控制空串儿和进位的情况。

    总结:

    这次并没有算法上的优劣比较,因为题目特性的原因,最简单直接的思路就是最有效的思路。而重点是对链表这种数据结构的操作熟练程度以及返回局部变量地址的方法的考察。


    cs