题目:给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字0之外,这两个数都不回以0开头。
示例
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
分析:
- 由于是用链表存储的整数,所以所表示的整数有可能会超过 int64 所能表示的整数范围,因此不能够直接把链表所表示的整数取出来相加,然后在存回链表。这就涉及到大整数相加的问题。
- 这种加法是逆序相加,设计大整数相加的时候要注意加法的方式。应该是从左边往右加,还需要考虑进位。
- 利用go语言中的切片来存储链表所表示的整数,然后,对两个切片进行特殊的加法。具体细节如下代码所示。
//getNumFromList函数:给定一个链表的表头,返回这个链表所表示的逆序整数
func getNumFromList(l *ListNode) []int {
var num []int
for {
if l == nil {
break
}
num = append(num, l.Val)
l = l.Next
}
return num
}
/*Special_Add函数:这个特殊的加法,特殊在:
1.它的输入是两个整数切片,对这两个整数切片进行相加
2.它是逆序相加,也就是两个切片从左边加到右边为止
*/
func Special_Add(num1 []int, num2 []int) []int {
var i, j int
var jinwei int //加法要考虑进位
var res []int
for {
if i < len(num1) && j < len(num2) {
//存储两数相加的余数作为结果,商作为进位
res = append(res, (num1[i]+num2[j]+jinwei)%10)
jinwei = (num1[i] + num2[j] + jinwei) / 10
i++
j++
} else {
break
}
}
//以下两种情况是考虑到两个整数切片的长度不一样所进行的特殊处理。
//如:999+11、11+9999这种情况
tag1:
if i == len(num1) && j != len(num2) {
res = append(res, (num2[j]+jinwei)%10)
jinwei = (num2[j] + jinwei) / 10
j++
goto tag1
}
tag2:
if i != len(num1) && j == len(num2) {
res = append(res, (num1[i]+jinwei)%10)
jinwei = (num1[i] + jinwei) / 10
i++
goto tag2
}
//下面是判断两个切片整数加完后,是否还存在进位,如88+22这种情况
if i == len(num1) && j == len(num2) && jinwei != 0 {
res = append(res, jinwei)
}
return res
}
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
//取出第一个链表所表示的逆序整数,存储在切片num1中
num1 := getNumFromList(l1)
//取出第二个链表所表示的逆序整数,存储在切片num2中
num2 := getNumFromList(l2)
//对两个整数切片进行逆序相加,得到的结果存储在切片res中
res := Special_Add(num1, num2)
var i int
//将res中所表示的逆序整数用链表存储
var head, p, tail *ListNode
head = new(ListNode) //新建节点
head.Next = nil
p = head
tail = head
//不断迭代,把结果存回链表中
for i = 0; i < len(res); i++ {
tail = new(ListNode)
tail.Val = res[i]
tail.Next = nil
p.Next = tail
p = p.Next
}
return head.Next
}