题目描述
思路解析动画文字版
为什么要 k%n?k 可能比 n 大,右移 n 位等于没移,所以真正的位移是 k 对 n 取模。下面一步步演示。
先用指针 p 走一遍链表,边走边数长度 n。现在 p 在头节点 1,n=1。
p 向后挪一格到值 2,长度计数 n=2。继续往后走直到 next 为 null。
p 向后挪一格到值 3,长度计数 n=3。继续往后走直到 next 为 null。
p 向后挪一格到值 4,长度计数 n=4。继续往后走直到 next 为 null。
p 向后挪一格到值 5,长度计数 n=5。继续往后走直到 next 为 null。
p 向后挪一格到值 6,长度计数 n=6。继续往后走直到 next 为 null。
p 向后挪一格到值 7,长度计数 n=7。继续往后走直到 next 为 null。
p 向后挪一格到值 8,长度计数 n=8。继续往后走直到 next 为 null。
p 走到值 9,它的 next 是 null —— 这就是表尾。一路数下来 n=9。记住尾节点,下一步要用它接环。
长度 n=9,k=3。真正要移的位数 = k%n = 3%9 = 3。尾节点(值 9)已点亮,接下来把它接回头节点成环。
把尾节点 9 的 next 接回头节点 1(尾部出现「↺ 回到 1」)。整条链先连成一个环,这样从任意点断开都能重排顺序。
要在「新尾」后面断开。新尾 = 从头往后走 n−k%n = 9−3 = 6 步。q 先站在头节点 1(这是第 1 个,还需再走 5 步)。
q 向后挪一格到值 2(已走 2 步)。继续走够 6 步。
q 向后挪一格到值 3(已走 3 步)。继续走够 6 步。
q 向后挪一格到值 4(已走 4 步)。继续走够 6 步。
q 向后挪一格到值 5(已走 5 步)。继续走够 6 步。
q 共走了 6 步,停在值 6 —— 这就是「新尾」(断开后链表的最后一个)。它的下一个节点 7 将成为新头。
新尾 = 6,它后面的 7 就是新头。马上做两件事:新头 = 新尾.next;新尾.next = null。环会在这里被打断。
把新尾 6 指向 7 的箭头断成 ·(即 6.next = null)。此刻原尾 9 还接着头 1(环未拆),但新链的末尾已经定下。
环解除:原来「尾 9 → 头 1」的那根回边,现在成了新链中间的普通连接(9 后面接 1)。新头是 7,新尾是 6。
上行是物理链(节点没动,只是断点改了);下行是顺着新头 7 读出的逻辑顺序 7→8→9→1→2→3→4→5→6。这正是右移 3 位的结果,返回新头 7。
空链 / 单节点 / k 是 n 倍 这三种先想清,取模和空判天然覆盖。
「成环 + 定位新尾断开」是各种链表整体平移的通用套路。
参考代码
def rotateRight(head, k): if not head or not head.next or k == 0: return head # ① 走到尾、数长度 n n, tail = 1, head while tail.next: tail = tail.next; n += 1 k %= n # ② k 对 n 取模 if k == 0: return head tail.next = head # ③ 尾连头成环 # ④ 从头走 n-k 步到新尾 newTail = head for _ in range(n - k - 1): newTail = newTail.next newHead = newTail.next newTail.next = None # 断开成新链 return newHead复杂度
- 时间:O(n),数长度走一遍 + 找新尾走 n−k 步,合计线性
- 空间:O(1),只用 tail / newTail / newHead 几个指针,原地改链
易错点
面试追问把动画讲成自己的话
追问为什么先成环再断,而不是直接找两段拼接?
追问左移 k 位怎么改?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。再去主线里挑下一道练手。
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题