一开始蒙对了思路 就很顺了 没有中等的难度
每次旋转一位后 原来的表尾变为表头 倒二的节点变为新的表尾 这个过程实现起来还是比较简单的 但仅对于旋转一位的情况
如果旋转多位 那么表尾就要不断更新 总不能每次都从头遍历找倒二的节点吧
考虑把原来的链表尾接头变为一个环 旋转的过程 其实就是头尾指针指向节点的变化
每旋转一位 其实就是尾指针向后移动一位 但后移没有next
指针支持 所以可以转换为前移$k$位
($k$怎么算?画个图模拟下一目了然 记节点总数位$cnt$ 后移$1$位 就相当于前移$(cnt - 1)$位)
(拓展到$i$:后移$i$位 如果$i \geq cnt$相当于绕了几圈回到原点再后移$(i\ mod\ cnt)$ 即前移$(cnt - (i\ mod\ cnt))$位)
上述找到了旋转后的新表尾 因为当前链表已经是个环 那么新表头就是表尾的下一位(tail.next
)
更新head
为tail.next
再把从环该位置断开 记tail.next=null
即为结果
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || head.next == null || k == 0) return head; // 事先过滤掉不用做处理的情况
int cnt = 1; // 记录节点总数 当前head也是一个节点 初始值为1
ListNode tail = head; // 记录表尾
while (tail.next != null) { // 循环统计节点个数 并找到表尾
cnt++;
tail = tail.next;
}
tail.next = head; // 闭合为环
k = cnt - k % cnt; // 计算尾指针需要前移的位数
for (int i = 0; i < k; i++) tail = tail.next; // 尾指针前移
head = tail.next; // 更新头指针
tail.next = null; // 环断开 表尾指向null
return head;
}
}