LEETCODE之链表 两数相加

题目:
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法1,常规解法

carry代表进位,由于进位只考虑对下一位的影响,所以每一次循环中,分别可能有要进位与不用进位的情况,都分别赋值carry=1和carry=0,否则在第一次进位后,carry一直为1。

由于最终要返回指向该链表的指针,所以定义了一个temp=p来存放起始位置,否则在不断创建新节点的过程中,单向链表将无法重新访问头节点。

注意在循环结束后,得到的和的数字的位数将于两个链表的其中的最长位数相同,故对于999+9999这样末尾还要进一位的就会有缺失,故在退出循环时加一层判断如果carry==1,说明还有一个进位没进,则p重新添加一个节点,并使val=1。

也可:不用carry作为flag来记录是否需要进位,而是再判断后,直接对p添加一个节点,并使那个节点的val=1,再把运算从p->val=l1->val+l2->val改成p->val+=l1->val+l2->val

​
​
​
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* add();
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode*p=add();
    struct ListNode*temp=p;
    int carry=0;
    while(1)
    {
        if((l1->val+l2->val+carry)>=10)
       {
             p->val=l1->val+l2->val-10+carry;//此时的carry是上一轮循环得到的carry
             carry=1;
       }
       else
       {
           p->val=l1->val+l2->val+carry;//此时的carry是上一轮循环得到的carry
           carry=0;
       }  
       if(l1->next!=NULL||l2->next!=NULL)//都到末尾时不满足if
       {
           if(l1->next==NULL)l1->next=add();
           if(l2->next==NULL)l2->next=add();
           l1=l1->next;
           l2=l2->next;
           p->next=add();
           p=p->next;
       }
       else break;
       
    }
    if(carry==1)
    {
         p->next=add();
           p=p->next;
           p->val=1;
    }
    return temp;
}
struct ListNode* add()
{
    struct ListNode*list=(struct ListNode*)malloc(sizeof(struct ListNode));
    list->val=0;
    list->next=NULL;
    return list;
}

​

​

​

 

进阶解法:递归

转载:

实现两个链表的每个节点互相加和,然后输出。这个题的关键点在于进位。
当某个节点的和大于10之后,需要向前进1位,在进位之后可能下一个节点之和加上进的1可能又会大于10,故我们可以使用递归的算法来完成这道题。

这题还有一个容易出现的问题,那就是两个链表不等长,当一个长一个短的时候,我们在判断链表是否到达终点将出现困难,我的策略是:如果其中一个链表的 next==Null那么我们使用malloc函数给他补上一个,让他的val==0这样即对我们的加和没有影响,又可以使两根链表等长。
 


struct ListNode* addNode();
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    l1->val = l1->val+l2->val;
    if(l1->val>=10)
	{	//进位
        l1->val -= 10;
        if(l1->next==NULL)
		{	//如果下一个为空了,则补一个节点再进位
            l1->next = addNode();
            l1->next->val += 1;
        }
		else
		{
            l1->next->val += 1;
        }
    }
    //两个链表都没有下一个节点,且不需要进位则直接输出
    if(l1->next==NULL&&l2->next==NULL&&l1->val<10)
	{
        return l1;	
    }
  	//判断l1下一个是否位空
    if(l1->next!=NULL)
	{
    //l1、l2下一个都不为空
        if(l2->next!=NULL)
		{
        //则直接递归
            l1->next = addTwoNumbers(l1->next,l2->next);
        }
		else
		{
        //l1不空,l2空,则补一个节点给他再递归
            l2->next = addNode();
            addTwoNumbers(l1->next,l2->next);
        }
    }
	else
	{
    //l1空,则补节点再递归
        l1->next = addNode();
        l1->next = addTwoNumbers(l1->next,l2->next);
    }
    //返回l1的指针
    return l1;
}
/*
	用于在一个链表到终点后,另一个链表还未到。添加一个节点上去
*/
struct ListNode* addNode(){
        struct ListNode* listt=(struct ListNode*)malloc(sizeof(struct ListNode));
        listt->val=0;
        listt->next=NULL;
        return listt;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值