143. 重排链表
1. 题目
给定一个单链表
L的头节点head,单链表L表示为:1
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
1
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:

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

1
2输入:head = [1,2,3,4,5]
输出:[1,5,2,4,3]提示:
- 链表的长度范围为
[1, 5 * 104] 1 <= node.val <= 1000
- 链表的长度范围为
2. 思路
a. 栈 & 队列
- 依赖栈的”先进后出“和队列的”先进先出“特性,遍历一次原始链表,将节点分别写入栈变量
leftQueue和队列变量rightStack中 - 依赖着上述写入的
leftQueue和rightStack俩集合特性和上述遍历的链表长度,使用遍历下标配合算术取余特性分别:- 当索引下标对2取余结果为奇数时,从队列取出节点(此处取出的依次是
L0, L1, L2)作为现有节点的下一个节点 - 当索引下标为2取余结果为偶数时,从栈取出节点(此处取出的依次是
Ln, Ln-1, Ln-2)作为现有节点的下一个节点
- 当索引下标对2取余结果为奇数时,从队列取出节点(此处取出的依次是
- 顺延当前节点至下一个
next指针 - 在遍历完链表长度后,当前节点便是最终链表的最后一个节点,此时需要该节点的
next指针进行置空操作,防止形成循环链表
b. 双指针
- 依赖列表的下标索引便捷性,遍历一次原始链表,将节点按下标顺序写入
list列表变量 - 生成左指针
l和右指针r,依据上述得到的列表变量list,同时开启循环对该两处下标的节点进行next指针的变更 - 在每次变更结束后,左指针
l向右移动一个单位,右指针r向左移动一个单位,直至l >= r - 当上述循环结束后,对结尾指针的
next指针进行置空操作,防止形成循环链表
3. 代码
a. 栈 & 队列
1 | /** |
b. 双指针
1 | /** |
4. 复杂度
两种解法,相比来讲,个人认为栈 & 队列更加形象和便于记忆,但使用到的空间也会比双指针多一倍,空间复杂度实际上是
O(2n),双指针做法相对来讲则性能更高
a. 栈 & 队列
- 时间复杂度:
O(n) - 空间复杂度:
O(n)

b. 双指针
- 时间复杂度:
O(n) - 空间复杂度:
O(n)
