Swift 数据结构与算法( 22) 链表 + S_Leetcode206. 反转链表(举例)

48 阅读1分钟

206. 反转链表

题目

给你单链表的头节点 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. 使用你的右手,从左边拿起第一张卡片(1),这张卡片就相当于 current
  2. 将这张卡片放到你的左手上(起初,左手是空的),现在这张卡片就变成了 prev
  3. 使用右手拿起下一张卡片(2),这也是 current
  4. 现在,把左手上的卡片(1)放在右手的卡片(2)下面。
  5. 然后,将组合好的两张卡片放回左手,接着用右手拿起下一张。
  6. 重复这个过程,直到所有的卡片都在你的左手上,且顺序已经反转。

在这个比喻中:

  • 你的左手代表 prev,它保存了你已经处理(反转)的卡片。
  • 你的右手代表 current,你正在处理这张卡片。
  • 当你把左手上的卡片放在右手的卡片下面时,这就相当于在代码中把 current.next 设置为 prev
  • 当你将组合好的卡片移到左手时,这就相当于更新 prevcurrent

个人易错点

while current?.next != nil {

分析错误原因:

  1. 思维定势:当处理链表问题时,很容易专注于节点之间的连接关系,例如 current.next。在这个过程中,你可能会忘记考虑整个节点(例如 current)的状态和位置。

  2. 漏掉边界条件:在处理链表时,经常要考虑头节点、尾节点和链表长度为0或1的特殊情况。在这种情况下,由于只检查了 current?.next 而不是 current,导致当链表只有一个节点或为空时,代码不会正常工作。

  3. 明确思考:在编写代码之前,先搞清楚你的目标。在这个例子中,目标是遍历整个链表,所以应该检查整个节点是否为 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 酱, 山景城一姐,