【链表】力扣24:两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例:
输入:head = []
输出:[]
迭代
-
创建头结点 dummy,令 dummy.next = head
-
cur 表示当前到达的结点,初始时 cur = dummy。每次需要交换 cur 后面的两个结点
-
当 cur 后面至少有两个结点(指针为 cur.next 和 cur.next.next),获取 cur 后面的两个结点 node1 和 node2,通过更新结点的指针关系实现这两个结点的两两交换(交换之前的结点关系是 cur -> node1 -> node2,交换之后的结点关系变为 temp -> node2 -> node1)
# 改变的顺序其实就是原结点顺序 cur、node1、node2
cur.next = node2 # 先改变指针 cur 指向的结点
node1.next = node2.next # 再改变指针 node1 指向的结点
node2.next = node1 # 最后是指针 node 指向的结点
-
令
cur = node1(此时 node1 已被交换,相当于 cur 往前进了两个结点,即cur = cur.next.next),对链表中的其余结点进行两两交换,直到全部节点都被两两交换 -
当 cur 的后面没有结点或者只有一个结点,就没有需要交换的了,此时结束循环
-
交换完成,链表 head 变了,但新的链表的头结点依旧是 dummy,dummy.next 依旧指的是跟在 dummy 后面的链表,因此返回新的链表 dummy.next 即可。

存在的问题:ListNode(0)和ListNode(-1)都是指构造的头结点吗???
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
dummy = ListNode(0)
dummy.next = head
cur = dummy
while cur.next and cur.next.next:
node1, node2 = cur.next, cur.next.next # 定义
cur.next, node1.next, node2.next = node2, node2.next, node1 # 交换
# cur 变换位置,为下一轮循环作准备
cur = node1 # cur = cur.next.next
return dummy.next
时间复杂度:O(n),其中 n 是链表的节点数量。需要对每个结点进行更新指针的操作。
空间复杂度:O(1)。
递归
递归主要需要搞清楚 递归的终止条件 & 递归函数的作用。
-
本题递归的终止条件是链表中没有结点,或者链表中只有一个结点,此时均无法进行交换
-
递归函数:将结点1 head 指向下一层的递归函数,结点2 head.next 指向结点1 head,最后返回
如果链表中至少有两个结点,则在两两交换链表中的结点之后,原始链表的第一个结点变成新的链表的第二个结点,原始链表的第二个结点变成新的链表的第一个结点。
链表中的其余结点的两两交换可以递归地实现。
在对链表中的其余结点递归地两两交换之后,更新结点之间的指针关系,即可完成整个链表的两两交换。
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
# 递归的终止条件
if not head or not head.next: # if not (head and head.next):
return head
temp = head.next # 保存结点2。所以最后要返回的结点2也就是temp
head.next = self.swapPairs(temp.next) # 结点1后面的结点利用递归调用发生交换,结点1的指针不再指向结点2,但此时结点2的指针没变
temp.next = head # 结点2指向结点1
return temp
时间复杂度:O(n),其中 n 是链表的节点数量。需要对每个节点进行更新指针的操作。
空间复杂度:O(n),其中 n 是链表的节点数量。空间复杂度主要取决于递归调用的栈空间。
stack作为中转站
-
每次取出两个结点放入 stack 中,再从 stack 中拿出两个结点
- 借助 stack 后进先出的特点,放进去的时候是 [1, 2]。拿出来的时候就是 [2,1] 了。
-
把这两个结点串联起来,重复这个逻辑,遍历整个链表,就可以做到两两交换的效果

虽然用到了 stack,但因为只存了两个元素,所以空间复杂度还是 O(1),时间复杂度是 O(n)。
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
# 终止条件
if not (head and head.next):
return head
p = ListNode(-1) # 创建虚拟头结点
cur, head, stack = head, p, [] # 让head指向p,返回的时候返回 head.next 就行
while cur and cur.next:
_,_ = stack.append(cur), stack.append(cur.next)
cur = cur.next.next
p.next = stack.pop()
p.next.next = stack.pop()
p = p.next.next
p.next = cur # 不管 cur 是否为空都可以让 p.next 指向cur
return head.next
近日总结:我比较适合用迭代法



浙公网安备 33010602011771号