概念
动画视频概念讲解: www.youtube.com/watch?v=o81…
比喻:
想象一下,你正在参加一场舞会。舞者们成对地跳舞,每对中有一名领舞者(first)和一名随舞者(second)。你是舞蹈老师,你的目标是让每对中的舞者交换位置,但他们需要继续手牵手跳舞。
-
开始时:舞者们已经准备好,成对地站着。
-
选定一对:你走到当前的一对舞者前:领舞者(
first)和随舞者(second)。 -
了解下一对:在指导他们交换前,你先看了看他们后面的一对舞者,这就是他们接下来要与之跳舞的舞伴,也即
next。 -
交换位置:
- 你首先告诉领舞者(
first)他们接下来会跟哪一对舞者跳舞,也就是与next连接。 - 接着,你告诉随舞者(
second)牵着领舞者(first)的手,站到最前面。 - 然后,你指导领舞者(
first)退到随舞者(second)的位置。此时,领舞者和随舞者交换了位置,但他们仍然手牵手。
- 你首先告诉领舞者(
-
继续指导:你继续前进,来到下一对舞者前,准备为他们指导交换。
这个舞蹈的比喻中,通过手牵手确保了每对舞者的连续性,就如同链表中的节点链接。
题目
24. 两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入: head = [1,2,3,4]
输出: [2,1,4,3]
示例 2:
输入: head = []
输出: []
示例 3:
输入: head = [1]
输出: [1]
提示:
- 链表中节点的数目在范围
[0, 100]内 0 <= Node.val <= 100
解题思路🙋🏻 ♀️
错误思考🤔
在每次交换后,需要将 first 和 second 移到下一个要交换的节点对上。否则,while 循环永远不会退出,因为 first 和 second 永远不会为 nil。
没有更新 first 和 second,这就导致了死循环,因为 first 和 second 永远不会变为 nil。
当时的错误可能是由于对题目理解不够深入或者在编码时的疏忽。为了避免此类错误,:
- 在编写代码之前,先用纸和笔画出算法的流程图。
- 编写代码时,务必确保处理了所有的边界条件。
- 使用调试工具或添加打印语句来跟踪代码的执行过程,确保它按照预期的方式工作。
- 练习和重复是关键。多做题,多思考,随着时间的推移,会更加熟悉这些模式,并能更容易地避免类似的错误。
代码
// 定义链表节点
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
}
}
时空复杂度分析
-
时间复杂度:O(n)
-
空间复杂度:O(1)
引用
本系列文章部分概念内容引用 www.hello-algo.com/
解题思路参考了 abuladong 的算法小抄, 代码随想录... 等等
Youtube 博主: huahua 酱, 山景城一姐,