Swift 数据结构与算法(23 )链表 + M_Leetcode24. 两两交换链表中的节点

76 阅读2分钟

概念

动画视频概念讲解: www.youtube.com/watch?v=o81…

比喻:

想象一下,你正在参加一场舞会。舞者们成对地跳舞,每对中有一名领舞者(first)和一名随舞者(second)。你是舞蹈老师,你的目标是让每对中的舞者交换位置,但他们需要继续手牵手跳舞。

  1. 开始时:舞者们已经准备好,成对地站着。

  2. 选定一对:你走到当前的一对舞者前:领舞者(first)和随舞者(second)。

  3. 了解下一对:在指导他们交换前,你先看了看他们后面的一对舞者,这就是他们接下来要与之跳舞的舞伴,也即 next

  4. 交换位置

    • 你首先告诉领舞者(first)他们接下来会跟哪一对舞者跳舞,也就是与 next 连接。
    • 接着,你告诉随舞者(second)牵着领舞者(first)的手,站到最前面。
    • 然后,你指导领舞者(first)退到随舞者(second)的位置。此时,领舞者和随舞者交换了位置,但他们仍然手牵手。
  5. 继续指导:你继续前进,来到下一对舞者前,准备为他们指导交换。

这个舞蹈的比喻中,通过手牵手确保了每对舞者的连续性,就如同链表中的节点链接。

截屏2023-08-10 17.23.49.png

题目

24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

 

示例 1:

输入: head = [1,2,3,4]
输出: [2,1,4,3]

示例 2:

输入: head = []
输出: []

示例 3:

输入: head = [1]
输出: [1]

 

提示:

  • 链表中节点的数目在范围 [0, 100] 内
  • 0 <= Node.val <= 100

解题思路🙋🏻‍ ♀️

错误思考🤔

在每次交换后,需要将 firstsecond 移到下一个要交换的节点对上。否则,while 循环永远不会退出,因为 firstsecond 永远不会为 nil

没有更新 firstsecond,这就导致了死循环,因为 firstsecond 永远不会变为 nil

当时的错误可能是由于对题目理解不够深入或者在编码时的疏忽。为了避免此类错误,:

  1. 在编写代码之前,先用纸和笔画出算法的流程图。
  2. 编写代码时,务必确保处理了所有的边界条件。
  3. 使用调试工具或添加打印语句来跟踪代码的执行过程,确保它按照预期的方式工作。
  4. 练习和重复是关键。多做题,多思考,随着时间的推移,会更加熟悉这些模式,并能更容易地避免类似的错误。

代码

// 定义链表节点
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 swapPairs(_ head: ListNode?) -> ListNode? {
        // 创建一个哑节点,使得处理头节点和其他节点一样
        let dummy = ListNode(0)
        // 哑节点指向头节点
        dummy.next = head
        // 创建一个前置节点,初始化为哑节点
        var prev: ListNode? = dummy
        
        while let first = prev?.next, let second = first.next { // 确保有两个节点可以交换
            // 更新第一个节点的next为第二个节点的next
            first.next = second.next
            // 第二个节点的next指向第一个节点
            second.next = first
            // 前置节点的next指向第二个节点
            prev?.next = second
            
            // 前置节点更新为第一个节点,为下一轮交换做准备
            prev = first
        }
        
        // 返回哑节点的next,即交换后的头节点
        return dummy.next
    }
}

时空复杂度分析

  1. 时间复杂度:O(n)

  2. 空间复杂度:O(1)

引用

本系列文章部分概念内容引用 www.hello-algo.com/

解题思路参考了 abuladong 的算法小抄, 代码随想录... 等等

Youtube 博主: huahua 酱, 山景城一姐,