题目简介:旋转链表(Rotate List)
LeetCode原题链接(题目编号:61):https://leetcode.com/problems/rotate-list/
将链表向右旋转 k 个位置。
示例:
- 输入:
1->2->3->4->5, k = 2 - 输出:
4->5->1->2->3
- 输入:
0->1->2, k = 4 - 输出:
2->0->1
约束条件:
- 链表长度
[0, 500] - 节点值
[-100, 100] 0 <= k <= 2 * 10^9
我的解题思路与优化过程
初版思路
- 尝试引入 dummy 节点,让所有指针操作更统一(tail、head 切换更方便)。
- 设定两个指针
start和end,同时遍历找到该断开重组的位置。 - 考虑让
end向后走n + 1步后,与start一起走,直到end为NULL,这样start指向新头、end_prev为新尾,重新接链。
但进一步思考发现:
- 需要先遍历一遍链表来获得其实际长度
len,进而用于k % len去"化简"大旋转步数。 - dummy 节点其实不是必须的,代码简化后逻辑会更清晰。
- 只需考虑特殊情况:空链表、单节点、多余旋转(
k % len == 0),直接返回不变。
正确且主流的官方解法
- 先遍历一遍得到长度
len。 - 用
k = k % len化简实际旋转长度。 - 快慢指针找到新的断链位置。 也就是第
(len-k)个节点为新尾,(len-k+1)为新头。 - 断链重组。 新尾指向
None,原链表尾接上原头(成环再断开)。
时间复杂度为何仍然是 O(n) 而不是 O(2n):
- 遍历两次都是 O(n),常数系数不影响大 O 记法。
dummy 节点其实可以不用
本题不涉及头部插入删除,所以直接操作 head 指针、处理 next 就够了,用 dummy 节点反而增加复杂度。
只要写清楚边界情况(空链表/单节点),后续断链按标准流程进行,不会有隐藏 bug。
面试官可能关心的问题
- 你有没有关注特殊情况的鲁棒性处理?
- 你明不明白 O(2n) 与 O(n) 没实质差异?
- dummy 节点的使用场景到底适不适合这题?
- 你能否说清,哪些链表题"必须 dummy"?哪些不用?
总结
- 旋转链表最优解法是"两遍遍历 + 断链重组",不是只为了代码简洁,更是因为它符合单链表操作的本质 & 性能极限。
- dummy 节点不是万能,使用要有场景;本题不用 dummy 更简明。
- 不用计较多一遍遍历,这种做法就是最优解,并且是官方推荐路线。
如需代码,只需进一步细节化流程步骤即可。
(注:本回答特意不贴出代码,体现面试交流思路为主的风格)
相关链接: