前言
让链表成闭环然后转起来帮我们解决问题,那么这就是我们用来解决旋转链表算法题的方法了
分析题目
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
以下我们定义链表节点总数为size:
- 首先从上面两张图我们可以分析出,将链表每个节点向右移动k个位置,其实就是将连接成环的链表向右旋转k个节点;
- 旋转两个节点可以理解为环尾部移动过来到原本环首部k个节点
- 比如k=1,size=5,那么5移动到环首,断开第
(size-k)个节点即断开成环后head起第4个节点,即可得到5->1->2->3->4; - k=2,size=5,那么4,5移动到环首,断开第
(size-k)个节点即断开成环后head起第3个节点,即可得到4->5->1->2->3; - 因为k是可能会大于链表节点的总数的,那我们需要对k取余操作,如果size是k的倍数相当于没有移动的,所以最后的余数才是我们节点真正移动的位置
k%size,那么最后断开成环链表的第(size-k%size)个节点即可获得我们的最终链表
- 比如k=1,size=5,那么5移动到环首,断开第
开始解题
var rotateRight = function(head, k) {
if(!head) return null;
let pre = head,cur = head,size=1; // 1、size从1开始,因为我们当前pre节点已经在第一个节点了
while(pre.next) { // 2、这一步循环是为了让pre指针走到链表的最后一个节点,
size += 1; // 如果pre的next指向null说明走到最后一个节点了,即pre.next为假跳出循环
pre = pre.next;
}
pre.next = cur; // 3、让pre.next指向cur即让cur成为pre的下一个节点,即链表的尾首相接成环;
for(let i=0; i < size - k%size -1; i++) { // 4、链表成环后就要考虑断开第几个节点拿到旋转后的链表
cur = cur.next; // 首先让cur指针从head节点移动到需要断开**指向下个节点的指针**的节点上
} // size - k%size -1这里我们size-k/%为什么要减1呢,因为我们cur指针已经在第一个节点上了
pre = cur.next; // 5、要断开当前节点与下个节点的指向时,首先保存下个节点,避免丢失丢失后面的节点
cur.next = null; // 断开cur所指向节点的下一个指向,那此时cur指向的节点为我们的尾节点
return pre; // pre所指向的就是我们新链表的头节点
};