61. 旋转链表(Rotate List)

难度:中等 | 主题:链表、双指针

题目

给你一个链表的头节点 head,旋转链表,将链表每个节点向右移动 k 个位置。

示例

 
输入:head = [1,2,3,4,5], k = 2
 
输出:[4,5,1,2,3]
 

思路

先讲个故事:循环队列出列

一群人坐成一圈,报数向右移动 K 位后重新排成一排。

实际上你不需要真的让每个人移动——你只需要找到新的起点在哪,然后从那里断开重排就行。


引导式推导:从暴力到成环断链

第 1 层:暴力(每次移动 1 位)

每次找到尾节点,让尾指向头,然后断开倒数第二个节点。重复 k 次。O(n×k),k 可能很大,慢到爆炸。

第 2 层:成环 + 求模(最优)

核心洞察:向右旋转 k 位 = 把最后 (k % n) 个节点搬到前面。

 
原始:①→②→③→④→⑤
 
k=2, n=5, k%n=2
 
步骤:
 
1. 成环:⑤→①
 
2. k%n=2,所以从原尾走 5-2=3 步,到达新尾 ③
 
3. ③.next = None,④ 是新头
 
结果:④→⑤→①→②→③
 

为什么是 n - k 步?

从头走到新尾需要 n - k - 1 步(0-indexed),从原尾走更简单——原尾走 n - k 步到新尾。


graph LR

    subgraph 成环断链法

        A["①→②→③→④→⑤<br/>k=2"] --> B["成环<br/>⑤→①"]

        B --> C["k%=2<br/>n-k=3步"]

        C --> D["新尾=③<br/>新头=④"]

        D --> E["断开: ③→None<br/>结果: ④→⑤→①→②→③"]

    end

    style E fill:#ffd700

解法时间空间
暴力逐位移O(n×k)O(1)
成环断链O(n)O(1)

代码

 
def rotateRight(self, head, k):
 
    if not head or not head.next:
 
        return head
 
    n = 1
 
    tail = head
 
    while tail.next:
 
        tail = tail.next
 
        n += 1
 
    k = k % n
 
    if k == 0:
 
        return head
 
    tail.next = head
 
    steps = n - k
 
    new_tail = tail
 
    for _ in range(steps):
 
        new_tail = new_tail.next
 
    new_head = new_tail.next
 
    new_tail.next = None
 
    return new_head
 

复杂度

指标解释
时间O(n)算长度 + 找新尾
空间O(1)几个指针

实战考量

频率分析

出现在:阿里/腾讯常考,约 15% 的 AI Agent 常会出这题。考察链表成环和断环的操作意识。

延伸思考

Q:为什么成环比暴力好?

A:暴力每次移动 O(n),共 k 次 O(nk)。成环法 O(n) + O(n) 一次搞定。

Q:向左旋转 k 个位置怎么做?

A:等价于向右旋转 n-k 个位置。或者改一下:找到新头的位置 = 正数第 k 个节点(不是倒数第 k 个)。

Q:如果 k 可能为负数呢?

A:负数表示向左旋转。k = k % n 后,如果 k < 0,k += n 转成正数。

Q:必须成环吗,不成都法怎么做?

A:可以不用成环——直接算新头位置,断开重连。但代码会多一个找新头前驱的步骤。

易错点

  • 忘记 k %= n,k 很大时无效旋转浪费时间

  • 成环后忘记断环,形成循环链表

  • steps 算错:是 n - k 不是 k


生活类比

旋转链表 → 移花接木

就像把一列队伍的最后几个人叫到最前面来——你不必让每个人真的”移动”,只需要告诉最后几个人”你们现在是第一名了,断开这里”。


相关题目

题目关系
189旋转数组数组版旋转

→ 返回题单:LeetCode学习路线图 > 四、链表

速记卡(面试闪卡)

Q1:一句话讲清「61. 旋转链表(Rotate List)」到底是什么?

A:旋转链表=把最后 k%n 个节点搬到前面;先成环再断链,从新尾断开即可,O(n) 空间 O(1)。

Q2:为什么要先成环? —— 怎么理解?

A:像把一列队伍最后几个人叫到最前面——你不必让每个人真移动,只需把队尾接回头成环,再从新尾断开。暴力每次搬一位 O(nk),成环法 O(n) 一次搞定。

Q3:新头新尾怎么定位? —— 怎么理解?

A:先遍历求长度 n 和尾节点,k=k%n 防止白转;新尾距原尾 n-k 步,新尾.next 即是新头。像数清楚队伍人数,才知道从第几个断开。

Q4:易错点? —— 怎么理解?

A:忘记 k%=n 大 k 时白转;成环后忘记断环会形成死循环链表;steps 是 n-k 不是 k。空表或单节点直接返回。

Q5:向左旋转或负 k? —— 怎么理解?

A:向左转 k 等价于向右转 n-k;负 k 先 k=k%n 再 k<0 则 k+=n。本质都是找”搬到前面的那截”的位置。

Q6:核心速记主线有哪些?

  • 核心:k%n 个尾节点搬到前,成环断链

  • 步骤:求长 n→k%=n→尾连头→走 n-k 步到新尾→断开

  • 复杂度:时间 O(n) 空间 O(1)

  • 易错:忘取模、忘断环、steps=n-k

口诀

A:链表旋转先成环,

尾接回头莫忘断;

k 取余后走 n-k,

新尾一掐头就换。

相关链接