程序员社区

两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

示例1:

在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

思路:

1. 先将l1和l2头节点的值加起来赋值给新链表的头节点 遍历两个链表,只要有一个链表还没有遍历到末尾,就继续遍历
2.每次遍历生成一个当前节点cur的下一个节点,其值为两链表对应节点的和再加上当前节点cur产生的进位 更新进位后的当前节点cur的值
3. 循环结束后,因为首位可能产生进位,因此如果cur.val是两位数的话,新增一个节点 返回头节点

#include<iostream>
using namespace std;
 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(l1->val+l2->val);//头指针指向第一个节点,第一个节点的val值是l1的个位加上l2的个位
		//head链表的移动指针
		ListNode* cur = head;
		//l1的移动指针
		ListNode* p1 = l1;
		//l2的移动指针
		ListNode* p2 = l2;
		//如果l1的长度较短,那么就在l2多出l1的位数补上0
		//例如:l1--->123   l2---->123456 ,那么l1补上0后的结果为123000,    l1+l2=123000+123456
		//因此循环结束的条件是l1和l2都为空
		while (p1->next!= NULL || p2->next!= NULL)
		{
			//如果l1->next!=NULL,那么p1=l1->next,否则就说明l1位数少,需要补上0
			//p1=l1->next是对l1链表的每个节点进行遍历,获得当前节点上的数字
			p1 = p1->next != NULL ? p1->next : new ListNode();//如果l1的位数较少,那么就在他最高位前面补上0,方便与l2进行相加操作
			p2 = p2->next != NULL ? p2->next : new ListNode();
			//生成head链表新的一个节点,用来存放当前遍历得到的l1+l2的val值
			//例如第一次循环获得的是l1和l2的十位上数字相加之和
			//这里还要加上cur指向当前节点的val值/10,是因为
			//例如:第一个两个整数个位相加得到的val=12,那么此时要进位,这里是尾插法,cur的next新节点存放的值是十位的值,因此12/10=1,那么十位进1
			cur->next = new ListNode(p1->val + p2->val+cur->val/10);
			//上个例子说到,cur的个位得到的之和为12,上面十位进1后,个位不应该再存储12,而应该是2,因此12%10=2
			cur->val %= 10;
			//再完成了进位操作后,cur指针就可以后移到十位
			cur = cur->next;
		}
		//如果循环结束后,cur的val值大于等于10,比如910+210,最后9+2=11,大于10,因此应该还要再进一位,到千位
		if (cur->val >= 10)
		{
			cur->next = new ListNode(cur->val/10);//因为还要再次前进一位到千位,所以还要再次开辟一个新节点,存放千位
			cur->val %= 10;//当前百位的11,再进位结束后,应该变为1
		}
		return head;
	}
};
//测试-----------------------------
ListNode* input(ListNode* l)
{
	cout << "请为当前链表赋值:" << endl;
	int num = 0;
	cin >> num;
	l->val = num;
	if (num == 0)
		return l;
	while (1)
	{
		cin >> num;
		if (num == 0)
			return l;
		ListNode* newNode = new ListNode;
		newNode->val = num;
		newNode->next = l;
		l = newNode;
	}
	return l;
}
//遍历链表
void display(ListNode* l)
{
	if (l == NULL)
		return;
	ListNode* move = l;
	cout << "遍历输出链表:" << endl;
	while (move)
	{
		cout << move->val;
		move = move->next;
	}
	cout << endl;
}
void test()
{
	ListNode* l1 = new ListNode;
	l1=input(l1);
	display(l1);
	ListNode* l2 = new ListNode;
	l2 = input(l2);
	display(l2);
	Solution s;
	ListNode* head =s.addTwoNumbers(l1, l2);
	//遍历head链表
	ListNode* p = head;
	int ret[10] = { 0 };
	int i = 0;
	//遍历head链表时,要逆序遍历,输出正确的顺序
	while (p)
	{
		ret[i] = p->val;
		i++;//顺便记录到底存储了几位数字
		p = p->next;
	}
	cout << i << "位数字" << endl;
	for (int j = i-1; j >= 0; j--)
	{
		cout << ret[j];
	}
}
int main()
{
	test();
	cout << endl;
	system("pause");
	return 0;
}

单链表逆序遍历的递归写法

//递归遍历
void output(ListNode* head)
{
	if (head == NULL)
		return;
	output(head->next);
	cout << head->val ;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

加法模板

<公式>

当前位 = (A 的当前位 + B 的当前位 + 进位carry) % 10 注意,AB两数都加完后,最后判断一下进位 carry,
进位不为 0 的话加在前面。

<加法模板>

while ( A 没完 || B 没完)
A 的当前位
B 的当前位

和 = A 的当前位 + B 的当前位 + 进位carry

当前位 = 和 % 10;
进位 = 和 / 10;
判断还有进位吗

赞(0) 打赏
未经允许不得转载:IDEA激活码 » 两数相加

相关推荐

  • 暂无文章

一个分享Java & Python知识的社区