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)