LeetCode 2.add Two Numbers

LeetCode 2.add Two Numbers (C语言)

这里直接截图来看了。

这里写图片描述

大致意思是给两个链表,将链表的各个对应位置的数字加起来得出一个新的链表。其实这是一个计算器的加法操作的实现。计算器接收输入时,它是一个数字一个数字接收的,所以250这个数字,接收到的是单独的2,5和0这几个数。上图的(2->4->3) + (5->6->4) = (7->0->8)其实看成数字就是342+465=807。 在计算器中,用户输入数字342是先输入一个3,再一个4,再一个2。这个输入的三个数就是上边的链表2->4->3的存放过程,在链表后边追加数字就行了。 而后续计算加法时,刚好是从个位开始计算,也就是链表的第一个。 所以整体弄下来,这个题最主要是解决进位的问题。


我们看下solution里边的提示发现几个比较特殊的用例需要我们考虑。

这里写图片描述

所以这个题我们可以先考虑最简单的情况[1] + [2]这种简单列表,通过测试后再考虑多个数的情况;然后再考虑两个列表长度不一样的情况;然后再考虑有进位的情况;然后再考虑不一样长度还会进位的情况。


贴下我的代码,不是最优的。不过看了下最优的那个(25ms),思路基本是一样的,只是调整了代码结构。然后多了个思路,即如果两个链表不一样长,就让短的那个后边的全部都为0,让两个列表长度一样长。 有兴趣的可以去官网看下最低用时的那个算法的源码。
(我代码里把/和%运算符换成加减运算,貌似时间没有变化。要改成位运算估计才会有点优化的效果。里边大量注释是我自己看的,请忽略之。)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    struct ListNode* retHead = NULL;//这个是用来返回的节点指针

    if(l1 != NULL && l2 != NULL){        
        struct ListNode* lastNode = NULL; //要返回的列表的最后一个节点
        struct ListNode* tempNode = NULL; //用来存放求出来的每一位的数字的新节点


        int addPromote = 0;//两个数字相加后需要进位的数字,一般是1或0
        int autoPromote = 0; //求出的数自己加上之前的进位,自己为0自动又进一位
        struct ListNode* node1 = l1;
        struct ListNode* node2 = l2;
        //1.这个是计算两个列表共有的节点个数的数字
        while(node1 != NULL && node2 != NULL){
            autoPromote = 0;
            int val1 = node1->val;
            int val2 = node2->val;
            tempNode = (struct ListNode*)malloc(sizeof(struct ListNode)); //先构造一个存放的节点
            tempNode->next = NULL; //这个一定要初始化,不然会报错
            if(retHead == NULL)//保存一下用来返回的头指针
                retHead = tempNode;

            int sum = val1 + val2;
            //int left = (val1 + val2) % 10;//求余得到此位置的数据
            int left = sum <= 9 ? sum:sum - 10;


            int now = left + addPromote; //当前位置上的数字

            //autoPromote = now / 10;//有可能当前位置上的数字加上上次的进位刚好又到了10,则下一位还需要进位一下
            //tempNode->val = now % 10; //求余才是正确的数字,直接赋值now有可能就是10. [9,8,9] [1,2]
            autoPromote = now <= 9 ? 0 : 1;
            tempNode->val = now <= 9 ? now : now - 10;

            if(lastNode != NULL)//表明不是第一次进来
                lastNode->next = tempNode;//添加到最后
            lastNode = tempNode;//指向最后一个

            //下次进来需要的数据
            //addPromote = (val1 + val2 + autoPromote) / 10;//进位的数字,
            addPromote = (sum + autoPromote) <= 9 ? 0 : 1;//进位的数字,

            node1 = node1->next;
            node2 = node2->next;
        }
        //2.从这里开始,表明某一个节点数字加完了,另外一个节点可能还有数字;[9,9,9,9] [2,1]
        struct ListNode* leftNode = node1 != NULL ? node1 : node2;
        if(leftNode != NULL){ //剩下的这个列表,唯一还可以加的数字就是之前第一步算完可能有的一个进位了
            lastNode->next = leftNode; //把最后多余的部分拼上去
            while(leftNode != NULL && addPromote > 0){ //如果后边还会自动进位的话还需要遍历算
                lastNode = leftNode;
                int now = leftNode->val + addPromote;
                //addPromote = now / 10;
                //leftNode->val = now % 10;
                addPromote = now <= 9 ? 0 : 1;
                leftNode->val = now <= 9 ? now : now - 10;
                leftNode = leftNode->next;
            }
        }

        if(addPromote > 0){ //最高位在进位之后自动大于了10,所以还要进位一次
            tempNode = (struct ListNode*)malloc(sizeof(struct ListNode)); //先构造一个存放的节点
            tempNode->next = NULL;
            tempNode->val = addPromote;//进位数据
            lastNode->next = tempNode;
        }
    }
    return retHead;
}

结果:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值