今天下午分享了一篇21题的链表操作,未了巩固一下自己的知识,在晚上的时候再刷了一题,也与链表相关的题目。
老规矩,先看题目
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.
「Exmaple」
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
我在没看清题目的情况下,妄自开始做题。结果很悲催,就是怎么做都做不出来,后来查了一下答案,发现我压根就看错题目了 !!!(大家千万别跟我一样,不然面试的时候就完蛋)
我是怎么理解错的呢, 题目中需要将3个数字相加,我脑海里浮现了2个百位数相加!
然后我直接开始按照小学加法的算法,对2个百位数进行计算(未考虑他已经反转好了),进位
然后我的进位则再需要一次单链表翻转,才能够完成任务,原本以为终于完成了,然而一提交「Wrong Answer」
好吧, 承认自己太粗心大意了, 但并非没收获, 当一看到正确答案的时候,灵光一闪直接懂了其中原理。
废话不少说,我们直接来看题目吧,就如例子所说, 有2个链表,里面各自有各自的数字,你要做的就是将其结果创建一个新的链表连起来, 要注意的是 进位的问题,
这道题目难点就在于其进位的问题, 我们先上代码
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
var result *ListNode = new(ListNode)
var head *ListNode
head = result
carry := 0
for l1 != nil || l2 !=nil {
d1:=0
d2:=0
if l1 == nil{ //防止该节点为null
d1 = 0
}else{
d1 = l1.Val
}
if l2 == nil{ //防止该节点为null
d2 = 0
}else{
d2 = l2.Val
}
sum := d1 + d2 + carry
if sum >= 10 {
carry = 1
}else {
carry = 0
}
var tmp *ListNode = new(ListNode)
tmp.Val = sum % 10
head.Next = tmp
head = head.Next
if l1 != nil{
l1 = l1.Next
}
if l2 != nil {
l2 = l2.Next
}
}
if carry == 1{
var tmp *ListNode = new(ListNode)
tmp.Val = 1
head.Next = tmp
}
return result.Next
}
老规矩,咱们还是顺序来, 头3行代码跟我上一篇(合并有序列表)的介绍一样, 这里不详细说明,只是一图带过就好, 需要详细的去参考我上一篇文章
head 就是 result本身, 为的是返回的时候,要返回链表的头部回去
然后我们定义了
carry := 0
初始化进位标识符为0
if l1 == nil{ //防止该节点为null
d1 = 0
}else{
d1 = l1.Val
}
if l2 == nil{ //防止该节点为null
d2 = 0
}else{
d2 = l2.Val
}
防止节点为nil的时候造成错误
d1:=0
d2:=0
sum := d1 + d2 + carry
这三句主要是将两数与进位符号相加, 就跟我们做的加法题一样
5 + 5 必须进位1
if sum >= 10 {
carry = 1
}else {
carry = 0
}
这个If主要是判断需不需要进位
var tmp *ListNode = new(ListNode)
tmp.Val = sum % 10
head.Next = tmp
head = head.Next
来重头戏了, 「sum%10」就是取个位的数字, 如果不懂的可以往前翻我第12题,罗马数字的解题思路
取得数值的个位,创建一个节点,并把head.next指向这个节点,这里咱们画个图解释
每一次的相加,都会创建出一个Temp的节点,并把head.Next指向他,再把head指向Temp(相当于往后移了一位),我们再来看个完整版本
每次循环后,再把题目给予的链表往后移一位
if l1 != nil{
l1 = l1.Next
}
if l2 != nil {
l2 = l2.Next
}
到这里我们就解释完了9成的代码了,剩下最后一块
if carry == 1{
var tmp *ListNode = new(ListNode)
tmp.Val = 1
head.Next = tmp
}
这里零散的多了一块 carry ==1 的例子是什么意思?
我们画个图,你就懂了
没错, 就是当链表长度是1的时候, 要进位,但l1 和 l2 的next确是空的情况下,我们也要对进位的Carry 1进行链表操作
到这里就完结散花了, 继续加油