算法题-第二周

算法题-第二周

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]

解题思路演进:

考虑先将短链表补0对齐长链表,需要计算两个链表的长度,然后在短链表尾部添加0,最后翻转去相加(过于复杂)

-> 先翻转两个链表,再从链头开始取出值拼成字符串,再转换成整型,将两个值相加,再倒叙生成新链表(由于链表长度可能是*100,整型放不下,long 都放不下)

-> 查看他人解题思路,由于是已经翻转的链表,所以从头结点开始相加就是低位开始相加,只要两个链表其中一个的后继节点有值就可以不断取出求和,另一个链表为空则取 0,再与进位相加。结果除 10 为进位,结果取余为新结点的值

kotlin代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? {
val root = ListNode(0) //根节点,最终生成的链表
var cursor = root //指向根节点,实际用来赋值的引用
var r1 = l1
var r2 = l2
var carry = 0//进位
while (r1 != null || r2 != null || carry != 0) {//链表后继结点或进位不为0则维持循环
val value1 = r1?.`val` ?: 0
val value2 = r2?.`val` ?: 0
val result = value1 + value2 + carry
carry = result / 10 //进位

val newNode = ListNode(result.rem(10))//结点取余赋值
cursor.next = newNode
cursor = cursor.next!!

if (r1 != null) r1 = r1.next
if (r2 != null) r2 = r2.next
}
return root.next
}

2.反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

kotlin代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun reverseList(head: ListNode?): ListNode? {
head?.also {
if (it.next == null) {
return head
}
var cur: ListNode? = it
var new: ListNode? = null
var next: ListNode? = null
while (cur != null) {
next = cur.next
cur.next = new
new = cur
cur = next
}
return new
}
return head
}
作者

ChinnSenn

發表於

2021-03-19

更新於

2023-04-20

許可協議

評論