Skip to content

Commit 32ea760

Browse files
committed
1. 0024-Swap-Nodes-in-Pairs2.md
1 parent e5ede1a commit 32ea760

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed
2.49 MB
Binary file not shown.
9.13 MB
Loading
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# LeetCode 第 24 号问题:两两交换链表中的节点
2+
3+
> 本文首发于公众号「图解面试算法」,是 [图解 LeetCode ](<https://github.com/MisterBooo/LeetCodeAnimation>) 系列文章之一。
4+
>
5+
> 同步博客:https://www.algomooc.com
6+
7+
题目来源于 LeetCode 上第 24 号问题:两两交换链表中的节点。
8+
9+
### 题目描述
10+
11+
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
12+
13+
**你不能只是单纯的改变节点内部的值**,而是需要实际的进行节点交换。
14+
15+
**示例:**
16+
17+
```
18+
给定 1->2->3->4, 你应该返回 2->1->4->3.
19+
```
20+
21+
### 题目解析 - 迭代法
22+
23+
由题目描述可知需要两两交换, 那么以两个为一组子链表交换指针即可, 在设置一个 **哨兵** 指向交换后的子链表 (或者哨兵提前指向子链表的第二个节点,因为第二个节点交换后就成了第一个节点); 然后让哨兵指向下一组子链表,继续交换,直至最后.
24+
25+
**哨兵** 为 节点 `prev`, 子链表第一个节点为 `A`, 第二个节点为 `B`, 第三个节点为 `C`, 那么操作流程如下:
26+
27+
- 终止条件 `head == null && head -> next == null`
28+
1. prev -> B ( A -> B -> C )
29+
2. A - > C
30+
3. B -> A ( prev -> B -> A -> C )
31+
4. prev -> A
32+
5. head -> C
33+
6. 循环以上步骤
34+
35+
### 动画描述
36+
37+
![](https://blog-1257126549.cos.ap-guangzhou.myqcloud.com/blog/6kpyu.gif)
38+
39+
### 代码实现
40+
41+
```javascript
42+
/**
43+
* JavaScript描述
44+
* 迭代法
45+
*/
46+
var swapPairs = function(head) {
47+
let dummy = new ListNode(0);
48+
dummy.next = head;
49+
50+
let prevNode = dummy;
51+
52+
while (head !== null && head.next !== null) {
53+
// Nodes to be swapped
54+
let firstNode = head,
55+
secondNode = head.next;
56+
// Swapping
57+
prevNode.next = secondNode; // 放到交换前后都可以
58+
firstNode.next = secondNode.next;
59+
secondNode.next = firstNode;
60+
// Reinitializing the head and prevNode for next swap
61+
prevNode = firstNode;
62+
head = firstNode.next;
63+
}
64+
return dummy.next;
65+
};
66+
```
67+
68+
### 复杂度分析
69+
70+
- 时间复杂度:**O(N)**,其中 *N* 指的是链表的节点数量
71+
- 空间复杂度:**O(1)**
72+
73+
### 题目解析 - 递归
74+
75+
递归的思路和迭代类似, 都是分组交换. 具体来说这里的递归不是针对一个问题深入进去,而是不断向后推进.
76+
77+
- 每次递归只交换一对节点
78+
- 下一次递归则是交换下一对节点
79+
- 交换完成后返回第二个节点, 因为它是交换后的子链表新头
80+
- 递归完成后返回第一次递归的第二个节点, 这就是新链表的头结点
81+
82+
**注意:** 不要人肉递归, 更多关注整体逻辑
83+
84+
示例执行大致流程为:
85+
86+
- 终止条件: `(head == null) || (head.next == null)`
87+
1. 1 -> 2 -> 3 -> 4 ( 原始链表 )
88+
2. 1 -> 3 -> 4
89+
3. ( 2 -> 1 ) -> 3 -> 4 ( 第一次递归完成后返回原来的第二个节点, 也就是值为 2 的节点 )
90+
4. 2 -> 1 -> 3 -> null
91+
5. 2 -> 1 -> ( 4 -> 3 ) ( 第二次递归完成后返回原来的第二个节点, 也就是值为 4 的节点 )
92+
93+
### 动画描述
94+
95+
96+
97+
### 代码实现
98+
99+
```javascript
100+
/**
101+
* JavaScript描述
102+
* 递归法
103+
*/
104+
var swapPairs = function(head) {
105+
if (head == null || head.next == null) {
106+
return head;
107+
}
108+
// Nodes to be swapped
109+
let firstNode = head,
110+
secondNode = head.next;
111+
// Swapping
112+
firstNode.next = swapPairs(secondNode.next);
113+
secondNode.next = firstNode;
114+
115+
return secondNode;
116+
117+
};
118+
```
119+
120+
### 复杂度分析
121+
122+
- 时间复杂度:**O(N)**,其中 *N* 指的是链表的节点数量
123+
- 空间复杂度:**O(N)**, 递归过程使用的堆栈空间
124+
125+
126+
127+
![](../../Pictures/qrcode.jpg)
128+

0 commit comments

Comments
 (0)