Leetcode 2 :Add Two Numbers(两数相加(链表))(大数相加)

Desciption

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.
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

Example

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

Solution 1:

思路:直接从两个链表所表示数的个位加起(即两个链表同时从前往后遍历),逐位计算,并赋值给结果链表,直到一个遍历到尾。再单独处理另一个未到尾部的链表,难点在于进位的处理。尤其最后一位不能忘;还有就是链表的操作要熟练掌握!

#include <iostream>
#include <string>
#include <cstdlib>  // free(), malloc()
#include <cstdio>   // getchar()

using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
	if (!l1)	// 如果一个为空,直接返回另一个
		return l2;
	else if (!l2)
		return l1;
	else
	{
		ListNode *res = NULL;
		ListNode *p1, *p2, *p3, *pre;

		p3 = res;
		p1 = l1;
		p2 = l2;
		int flag = 0;	// 进位标志

		while (p1 != NULL && p2 != NULL)
		{
			p3 = new ListNode(0);

			if (res == NULL)
				res = p3;
			else
				pre->next = p3;

			p3->next = NULL;
			pre = p3;

			if (p1->val + p2->val + flag < 10)
			{
				p3->val = p1->val + p2->val + flag;
				flag = 0;
			}
			else
			{
				p3->val = p1->val + p2->val + flag - 10;
				flag = 1;
			}

			p1 = p1->next;
			p2 = p2->next;
		}

		while (p1)	// 进入此循环表示此时 l2 部分已运算完,l1未完
		{
			p3 = new ListNode(0);
			pre->next = p3;
			p3->next = NULL;
			pre = p3;

			if (p1->val + flag < 10)
			{
				p3->val = p1->val + flag;
				flag = 0;
			}
			else
			{
				p3->val = p1->val + flag - 10;
				flag = 1;
			}

			p1 = p1->next;
		}
		while (p2)	// 进入此循环表示此时 l1 部分已运算完,l2未完
		{
			p3 = new ListNode(0);
			pre->next = p3;
			p3->next = NULL;
			pre = p3;

			if (p2->val + flag < 10)
			{
				p3->val = p2->val + flag;
				flag = 0;
			}
			else
			{
				p3->val = p2->val + flag - 10;
				flag = 1;
			}

			p2 = p2->next;
		}

		if (flag)	// 判断最后一位是否进位
		{
			p3 = new ListNode(0);
			pre->next = p3;
			p3->next = NULL;
			pre = p3;
			p3->val = flag;
		}

		return res;
	}
}
/* 主函数,用来测试,输入时第一行输入 l1 各节点数据,空格隔开,回车结束输入,第二行输入 l2 各节点数据 */
int main(void)  
{
	ListNode *l1 = NULL;
	ListNode *l2 = NULL;

	ListNode *pre, *current;

	while (1)   // 逐位输入l1,以换行结束
	{
		current = new ListNode(0);

		if (l1 == NULL)
			l1 = current;
		else
			pre->next = current;

		current->next = NULL;
		pre = current;
		cin >> current->val;

		if (getchar() == '\n')
			break;
	}

	pre = NULL;
	current = NULL;

	while (1)   // 逐位输入l2,以换行结束
	{
		current = new ListNode(0);

		if (l2 == NULL)
			l2 = current;
		else
			pre->next = current;

		current->next = NULL;
		pre = current;
		cin >> current->val;

		if (getchar() == '\n')
			break;
	}

	ListNode *res = addTwoNumbers(l1, l2);
	current = res;

	while (current) // 输出结果
	{
		cout << current->val << " ";
		current = current->next;
	}
	cout << endl;

	current = l1;   // 释放 l1
	while (current)
	{
		current = l1->next;
		free(l1);
		l1 = current;
	}

	current = l2;   // 释放 l2
	while (current)
	{
		current = l2->next;
		free(l2);
		l2 = current;
	}

	current = res;   // 释放 res
	while (current)
	{
		current = res->next;
		free(res);
		res = current;
	}

	return 0;
}

结果:
在这里插入图片描述
个人感觉海星吧。


Solution 2:最简洁

ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) 
{
    ListNode preHead(0), *p = &preHead;
    int extra = 0;
    
    while (l1 || l2 || extra) 
    {
        int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
        extra = sum / 10;	// 进位
        p->next = new ListNode(sum % 10);
        p = p->next;
        l1 = l1 ? l1->next : l1;
        l2 = l2 ? l2->next : l2;
    }
    
    return preHead.next;
}

太tm强了。。。。最简洁(但复杂度非最优)的答案。
思路:其实跟上面我的代码是一个思路,,,但是这段代码巧妙运用三元运算符(l1 || l2 || extra)的关系,将整个计算过程统一起来。复杂度和 Solution 1 一样。
当然,如果想要更好的空间复杂度,则可以尽量用 l 1 , l 2 l1,l2 l1l2 中某个链表来存结果,这样便可节省许多空间!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值