题目
来源:LeetCode.
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
提示:
- 链表中节点的数目在范围 [ 0 , 100 ] [0, 100] [0,100] 内
- 0 < = N o d e . v a l < = 100 0 <= Node.val <= 100 0<=Node.val<=100
接下来看一下解题思路:
思路一:递归:
递归的终止条件是链表中没有节点,或者链表中只有一个节点,此时无法进行交换。
如果链表中至少有两个节点,则在两两交换链表中的节点之后,原始链表的头节点变成新的链表的第二个节点,原始链表的第二个节点变成新的链表的头节点。
链表中的其余节点的两两交换可以递归地实现。在对链表中的其余节点递归地两两交换之后,更新节点之间的指针关系,即可完成整个链表的两两交换。
用
h
e
a
d
head
head 表示原始链表的头节点,新的链表的第二个节点,用
n
e
w
H
e
a
d
newHead
newHead 表示新的链表的头节点,原始链表的第二个节点,则原始链表中的其余节点的头节点是
n
e
w
H
e
a
d
.
n
e
x
t
newHead.next
newHead.next。
令
h
e
a
d
.
n
e
x
t
=
s
w
a
p
P
a
i
r
s
(
n
e
w
H
e
a
d
.
n
e
x
t
)
head.next = swapPairs(newHead.next)
head.next=swapPairs(newHead.next),表示将其余节点进行两两交换,交换后的新的头节点为
h
e
a
d
head
head 的下一个节点。
然后令
n
e
w
H
e
a
d
.
n
e
x
t
=
h
e
a
d
newHead.next = head
newHead.next=head,即完成了所有节点的交换。最后返回新的链表的头节点
n
e
w
H
e
a
d
newHead
newHead。
public static ListNode swapPairs1(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = head.next;
head.next = swapPairs(newHead.next);
newHead.next = head;
return newHead;
}
总结
时间复杂度:
O
(
n
)
O(n)
O(n),其中
n
n
n 是链表的节点数量。
空间复杂度:
O
(
n
)
O(n)
O(n),其中
n
n
n 是链表的节点数量。
思路二:迭代:
创建哑结点 d u m m y dummy dummy,令 d u m m y . n e x t = h e a d dummy.next = head dummy.next=head。令 p r e d pred pred 表示当前到达的节点,初始时 p r e d = d u m m y pred = dummy pred=dummy。每次需要交换 p r e d pred pred 后面的两个节点。
如果 p r e d pred pred 的后面没有节点或者只有一个节点,则没有更多的节点需要交换,因此结束交换。否则,获得 p r e d pred pred 后面的两个节点 c u r cur cur 和 a f t e r after after,通过更新节点的指针关系实现两两交换节点。
具体而言,交换之前的节点关系是
p
r
e
d
−
>
c
u
r
−
>
a
f
t
e
r
pred -> cur -> after
pred−>cur−>after,交换之后的节点关系要变成
p
r
e
d
−
>
a
f
t
e
r
−
>
c
u
r
pred -> after-> cur
pred−>after−>cur
完成上述操作之后,节点关系即变成
p
r
e
d
−
>
a
f
t
e
r
−
>
c
u
r
pred -> after-> cur
pred−>after−>cur。再令
p
r
e
d
=
c
u
r
pred = cur
pred=cur,对链表中的其余节点进行两两交换,直到全部节点都被两两交换。
两两交换链表中的节点之后,新的链表的头节点是 d u m m y . n e x t dummy.next dummy.next,返回新的链表的头节点即可。
public static ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode dummy = new ListNode(-1, head);
ListNode pred = dummy;
while (pred.next != null && pred.next.next != null) {
ListNode cur = pred.next;
ListNode after = pred.next.next;
pred.next = after;
// 交换节点
cur.next = after.next;
after.next = cur;
// 下一次交换的前驱节点
pred = cur;
}
return dummy.next;
}
总结
时间复杂度:
O
(
n
)
O(n)
O(n),其中
n
n
n 是链表的节点数量。
空间复杂度:
O
(
1
)
O(1)
O(1)。