1-链表-两数相加

这是链表篇章的第一篇,从现在开始要玩链表了。力扣链接

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

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

你可以假设除了数字 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]

这道题看起来很好玩,其实就是链表的头部为数字的最低位,让两个链表组成两个数相加,然后生成新的链表。

这道题老规矩可以玩玩暴力法,将两个链表变成数字然后相加。

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	left, right := calculateNumber(l1), calculateNumber(l2)
	sum := left + right
	result := &ListNode{
		Val: sum % 10,
	}
	sum /= 10
	last := result
	for sum != 0 {
		last.Next = &ListNode{
			Val: sum % 10,
		}
		sum /= 10
		last = last.Next
	}
	return result
}

func calculateNumber(n *ListNode) int {
	result, level := 0, 1
	for n != nil {
		result = result + n.Val*level
		level *= 10
		n = n.Next
	}
	return result
}

 代码虽然写好了,但是测试用例没过:

显然,这里越界了。 换了一下big.Int,还是越界,好的 放弃暴力方法了:

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	left, right := calculateNumber(l1), calculateNumber(l2)
	sum := big.NewInt(0).Add(left, right)
	result := &ListNode{
		Val: int(sum.Int64() % 10),
	}
	sum = big.NewInt(0).Div(sum, big.NewInt(10))
	last := result
	for sum.Sign() != 0 {
		last.Next = &ListNode{
			Val: int(sum.Int64() % 10),
		}
		sum = big.NewInt(0).Div(sum, big.NewInt(10))
		last = last.Next
	}
	return result
}

func calculateNumber(n *ListNode) *big.Int {
	result := big.NewInt(0)
	level := big.NewInt(1)

	for n != nil {
		val := big.NewInt(int64(n.Val))
		val.Mul(val, level)
		result.Add(result, val)
		level.Mul(level, big.NewInt(10))
		n = n.Next
	}
	return result
}

既然不暴力了,那就尝试一下双指针,其实就是模拟法,一个一个加,加完为止。

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	in := 0
	result := &ListNode{Next: nil}
	cur := result
	for l1 != nil || l2 != nil {
		left := 0
		if l1 != nil {
			left = l1.Val
			l1 = l1.Next
		}
		right := 0
		if l2 != nil {
			right = l2.Val
			l2 = l2.Next
		}
		sum := left + right + in
		cur.Next = &ListNode{
			Val: sum % 10,
		}
		cur = cur.Next
		in = sum / 10
	}
	if in != 0 {
		cur.Next = &ListNode{Val: in}
	}
	return result.Next
}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表中的两数相加是一个经典的问题,我们可以通过遍历链表并进行逐位相加来解决。具体的步骤如下: 1. 定义一个新的链表作为结果的头结点,并初始化为空。 2. 定义两个指针分别指向两个链表的头结点,以及一个进位变量carry,初始值为0。 3. 遍历两个链表,直到两个链表都遍历完。 4. 在每个节点上,将两个链表对应位置的值相加,并加上进位值carry。 5. 计算当前位置的值以及进位值,更新结果链表以及进位值。 6. 如果某个链表已经遍历完,但另一个链表还有剩余节点,则将剩余节点的值与进位值相加,并更新结果链表。 7. 如果最后一个节点的相加结果产生了进位,则在结果链表末尾添加一个值为1的新节点。 8. 返回结果链表的头结点。 下面是C++代码实现: ```cpp struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode* dummy = new ListNode(0); ListNode* curr = dummy; int carry = 0; while (l1 || l2) { int x = (l1) ? l1->val : 0; int y = (l2) ? l2->val : 0; int sum = carry + x + y; carry = sum / 10; curr->next = new ListNode(sum % 10); if (l1) l1 = l1->next; if (l2) l2 = l2->next; curr = curr->next; } if (carry > 0) { curr->next = new ListNode(carry); } return dummy->next; } ``` 这个算法的时间复杂度是O(max(m, n)),其中m和n分别是两个链表的长度。空间复杂度是O(max(m, n)),用于存储结果链表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值