Leetcode 2:两数相加

一题探秘迭代和递归

Leetcode 2: 两数之和是一道迭代和递归的主战场。
两数相加

图解

/*
 * @lc app=leetcode.cn id=2 lang=cpp
 *
 * [2] 两数相加
 */

// @lc code=start
/**
 * 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* head=new ListNode(-1);
	   //用来建造输出链表,节点cur从头开始。
        ListNode* cur=head;
	   //进位项
        bool flag=false;
        while(l1||l2||flag){
		   //数值的确定,为空就补0填充
            int v1=l1?l1->val:0;
            int v2=l2?l2->val:0;
		   //遍历到后一位
            if(nullptr!=l1) l1=l1->next;
            if(nullptr!=l2) l2=l2->next;
            int sum=flag?v1+v2+1:v1+v2;
		     //进位项每一次的结果都会被下一次的sum计算统计进入
            flag=sum>9?1:0;
		   //输出链表的构建
            ListNode* node=new ListNode(sum%10);
            cur->next=node;
            cur=node;
           
        }   
        return head->next;
    }
};

对于Leetcode:2两数相加而言,迭代遍历的方法性能最佳。
迭代直观上正序遍历,但链表节点的指针在遍历后指向链表尾部为空,不能一个指针节点重新回头部,返回输出链表(两数之和的返回值)。
punchline:在两数相加前新建一个哑节点head,head不移动,仅用于返回输出。
迭代遍历: while语句只有当l1和l2且flag都不为真才退出 即: L1为空,L2为空,flag进位为false,才不需要新开辟一个节点

/*
 * @lc app=leetcode.cn id=2 lang=cpp
 *
 * [2] 两数相加
 */

// @lc code=start
/*
 * 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) {
        //进制位
        int flag=false;
        ListNode* head =recursion(l1,l2,flag);
        return head;
    }
    ListNode* recursion(ListNode* l1,ListNode* l2,bool flag){
        //计算终止条件
        //如果l1,l2为空,且flag=false
        if(!(l1||l2||flag)) return nullptr;
        int v1=l1?l1->val:0;
        int v2=l2?l2->val:0;
        int sum=flag?v1+v2+1:v1+v2;
        flag=sum>9?true:false;
        //对同位节点计算完毕,递归下一位
        if(nullptr!=l1) l1=l1->next;
        if(nullptr!=l2) l2=l2->next;
        ListNode* cur=new ListNode(sum%10); 
        ListNode* NEXT=recursion(l1,l2,flag);
        cur->next=NEXT;
        return cur;
    }

递归也可以解决上面的问题:
难点是:进制位的传递,所以递归函数签名是ListNode* recursion(ListNode* l1,ListNode* l2,bool flag)
在递归过程前,可以看成先序遍历。应该已经计算所有的当前节点和,生成新节点
递归函数返回值是得到下一个节点,返回给当前节点,即连接当前节点和下一个节点。递归的Base case是 l1为空,l2为空并且flag==false,意味着不会创建新的节点,该节点是终止节点。
在递归过程后,可以看成后序遍历,应该将递归返回的后一位和当前创建的节点连接成链表,
然后返回当前节点给上一个节点的递归。

递归和迭代这两兄弟还真是我道路上的拦路虎啊。
最重要的是适合(合适),迭代确实在两数之和上占尽优势!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值