题目
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]
示例 2:
输入: head = [1,2]
输出: [2,1]
示例 3:
输入: head = []
输出: []
提示:
- 链表中节点的数目范围是
[0, 5000] -5000 <= Node.val <= 5000
进阶: 链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
概念
举例说明
想象正在整理一叠卡片,每张卡片上都有一个数字,卡片从左到右顺序排列。你的目标是将这些卡片的顺序完全反转。
现在,你只有两只手,所以你不能同时抓住所有的卡片。但是你可以一次抓住一张,或者挪动一张。
初始状态: 卡片摆在桌子上,顺序为 1 2 3 4 5。
反转操作:
- 使用你的右手,从左边拿起第一张卡片(
1),这张卡片就相当于current。 - 将这张卡片放到你的左手上(起初,左手是空的),现在这张卡片就变成了
prev。 - 使用右手拿起下一张卡片(
2),这也是current。 - 现在,把左手上的卡片(
1)放在右手的卡片(2)下面。 - 然后,将组合好的两张卡片放回左手,接着用右手拿起下一张。
- 重复这个过程,直到所有的卡片都在你的左手上,且顺序已经反转。
在这个比喻中:
- 你的左手代表
prev,它保存了你已经处理(反转)的卡片。 - 你的右手代表
current,你正在处理这张卡片。 - 当你把左手上的卡片放在右手的卡片下面时,这就相当于在代码中把
current.next设置为prev。 - 当你将组合好的卡片移到左手时,这就相当于更新
prev和current。
个人易错点
while current?.next != nil {
分析错误原因:
-
思维定势:当处理链表问题时,很容易专注于节点之间的连接关系,例如
current.next。在这个过程中,你可能会忘记考虑整个节点(例如current)的状态和位置。 -
漏掉边界条件:在处理链表时,经常要考虑头节点、尾节点和链表长度为0或1的特殊情况。在这种情况下,由于只检查了
current?.next而不是current,导致当链表只有一个节点或为空时,代码不会正常工作。 -
明确思考:在编写代码之前,先搞清楚你的目标。在这个例子中,目标是遍历整个链表,所以应该检查整个节点是否为
nil,而不仅仅是它的.next属性。
代码
class Solution {
func reverseList(_ head: ListNode?) -> ListNode? {
var prev:ListNode? = nil
var current = head
var next:ListNode? = nil
while current != nil {
next = current?.next
current?.next = prev
prev = current
current = next
}
return prev
}
}
时空复杂度分析
O(n)
引用
本系列文章部分概念内容引用 www.hello-algo.com/
解题思路参考了 abuladong 的算法小抄, 代码随想录... 等等
Youtube 博主: huahua 酱, 山景城一姐,