原题链接:61. 旋转链表
解题思路:
- 输入:
head = [1,2,3,4,5], k = 2
。 - 如果将链表连接成环,会变成这样的样子:
[1,2,3,4,5,1,2,3,4,5, ...]
。 - 此时我们只要将
3 → 4
的连接打断,即可得到结果:[4,5,1,2,3]
。 - 可以把问题按步骤解决:
- 创建两个指针,
slow = 1, fast = 1
。 - 将
fast
向前移动2
位,指向3
。 - 再将
slow
和fast
同时向前移动,知道fast
指向尾结点,此时slow
正好停留在链表要断点的位置。 - 将
fast
与head
连接,让链表形成环。 - 缓存新链表的头结点
const newHead = slow.next
,将链表打断slow.next = null
- 将新链表的头结点
newHead
返回。
- 创建两个指针,
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var rotateRight = function (head, k) {
// 以下条件无需旋转,直接返回即可
if (
// 链表为空
!head ||
// 链表只有一个节点
!head.next ||
// 旋转数量为0
k === 0
) {
return head;
}
// 使用一个指针,统计链表长度
let node = head;
// 统计节点数量,指针初始指向头结点,因此初始值为1
let length = 1;
// 不断移动指针,但它停在尾结点时,完成链表长度的统计
while (node.next) {
length++;
node = node.next;
}
// 创建快慢指针,初始时都指向头节点
let slow = head;
let fast = head;
// 链表旋转节点数量,k可能大于链表长度,因此需要取余
k = k % length;
// 如果k为0,无需旋转,直接返回即可
if (k === 0) {
return head;
}
// 将快指针向前移动k位,此时快慢指针的距离为k
while (--k >= 0) {
fast = fast.next;
}
// 将快指针移动到尾结点,此时慢指针停留在需要打断点的节点
while (fast.next) {
slow = slow.next;
fast = fast.next;
}
// 将快指针与原链表头结点连接,让链表形成环
fast.next = head;
// 新链表的头结点在慢指针的下一个节点,将其缓存
const newHead = slow.next;
// 将慢指针与新链表头结点打断
slow.next = null;
// 返回新链表
return newHead;
};