「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。
前言
一直都计划学习数据结构与基本算法,但是平时都看一阵停一阵。现在决心坚持下去,我准备从LeetCode的HOT100开始,每天完成1~2道习题,希望通过这种方式养成持续学习的习惯。因为我是做iOS开发的,主要是用Objective-C语言,最近也在学习Swift,所以本系列的题解都将使用swift语言完成,本文更新的是LeetCode中HOT100的第2题002两数相加。
题目
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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]
分析
本题的意义其实就是两个整数的加法计算的模拟过程,由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。
我们同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。具体而言,如果当前两个链表处相应位置的数字为 n1,n2,进位值为 carry,则它们的和为 n1+n2+carry;其中,答案链表处相应位置的数字为(n1+n2+carry)mod10(此处的mod表示求余),而新的进位值为 (n1+n2+carry)/10 (此处的除/表示整除)。
如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0 。
此外,如果链表遍历结束后,有 carry>0,还需要在答案链表的后面附加一个节点,节点的值为
carry。
题解
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init() { self.val = 0; self.next = nil; }
* public init(_ val: Int) { self.val = val; self.next = nil; }
* public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
* }
*/
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
//有一个链表为空时,不用计算,直接返回另一个链表即可
if l1 == nil { return l2 }
if l2 == nil { return l1 }
var addVal = 0 //进位上的值carry
var curl1 = l1 //链表1当前的值 n1
var curl2 = l2 //链表2当前的值 n2
var curResNode:ListNode? = nil //结果链表的当前节点
var ansNode :ListNode? = nil //结果链表的头结点
while curl1 != nil || curl2 != nil || addVal != 0 {
let tempAns = (curl1?.val ?? 0) + (curl2?.val ?? 0) + addVal
addVal = tempAns / 10 //计算进位上的值
let node = ListNode(tempAns%10) //创建当前结果节点
if curResNode == nil {
ansNode = node
curResNode = node
} else {
curResNode?.next = node
curResNode = node
}
//下一位上继续
curl1 = curl1?.next
curl2 = curl2?.next
}
curResNode?.next = nil
return ansNode
}
}