LeetCode61. 旋转链表

61. 旋转链表 ------ 三步成环法

这道题的核心在于:先连成环,再找断点,最后断开。


题目链接

题目简述

给定一个单链表和一个非负整数 k,将链表向右旋转 k 个位置。

例如:

  • 输入:1 → 2 → 3 → 4 → 5k = 2
  • 输出:4 → 5 → 1 → 2 → 3

解题思路

采用的"成环 + 找断点"的策略:

  1. 先成环:把链表的尾部指向头部,变成一个环形链表。
  2. 再找断点 :从头部开始走 n - k - 1 步(n 是链表长度),找到新的尾部。
  3. 最后断开 :把新尾部的 next 设为 nullptr,新头部就是它的 next

代码详解(配合示意图)

cpp 复制代码
ListNode* rotateRight(ListNode* head, int k) {
    if(head == nullptr) return nullptr;

    // 1. 找链表长度 n,并让 tem 指向最后一个节点
    ListNode* tem = head;
    int n = 1;  // 从1开始,因为至少要算上头节点
    while(tem->next != nullptr) {
        n++;
        tem = tem->next;
    }
    // 不能用下面的方法计算,这样最后扫描到的结点是空结点
		// int n = 0;
    // while(tem != nullptr)
    // {
    //     n++;
    //     tem = tem -> next;
    // }
    // 2. 连成环:让最后一个节点指向头节点
    tem->next = head;

    // 3. 计算实际需要移动的步数(取模避免越界)
    k = k % n;
    int x = 1;
    ListNode* p = head;

    // 4. 走 n - k -1步,找到新链表的尾部
    while(x <= n - k - 1) {
        x++;
        p = p->next;
    }

    // 5. 断开环,设置新的头尾
    head = p->next;  // 新的头是断点后的下一个节点
    p->next = nullptr;  // 断点处设为 nullptr

    return head;
}

图解过程

初始状态:

复制代码
head → 1 → 2 → 3 → 4 → 5 → nullptr

第一步:找长度和尾部

  • temhead 开始,走到 5
  • n = 5

第二步:成环

复制代码
5 → head → 1 → 2 → 3 → 4 → 5 (环形)

第三步:找断点

  • k = 2,所以 n - k - 1= 2
  • phead 出发,走 2 步:
    • 第1步:p = 2
    • 第2步:p = 3
  • 此时 p 指向 3,它是新链表的尾部。

第四步:断开环

  • head = p->next = 4

  • p->next = nullptr

  • 结果:

    4 → 5 → 1 → 2 → 3 → nullptr


关键点总结

  • 为什么 tem->next != nullptr

    因为我们想让 tem 最终停在最后一个节点 ,而不是 nullptr。如果写成 tem != nullptrtem 会走到 nullptr,那 tem->next 就炸了。

  • 为什么 n 从 1 开始?

    因为我们至少包含头节点。比如链表只有一个节点,n=1,循环不会执行,tem 还是头节点,没问题。

  • 为什么是 n - k - 1

    因为向右旋转 k 步,相当于把前 n - k 个节点移到后面。所以新尾部就是 是n - k 个节点本身

    比如 n=5, k=2,新尾部是第 3 个节点(索引从0开始),新头部是第 4 个节点。

  • 为什么 k = k % n

    如果 kn 大,比如 k=7, n=5,其实等价于 k=2,因为转一圈等于没转。


复杂度分析

  • 时间复杂度 :O(n)

    一次遍历找长度,一次遍历找断点,总共 2n,所以是 O(n)。

  • 空间复杂度 :O(1)

    只用了几个指针变量,没有额外空间。


小结

这道题用"成环法"非常优雅,避免了复杂的数组拷贝或多次遍历。配合你的手绘图,逻辑一目了然:

成环 → 找点 → 断开,三步搞定旋转链表。

画图真的很有帮助,尤其是链表这种结构,一眼就能看出指针怎么走、断在哪里。

相关推荐
徐小夕3 分钟前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei19 分钟前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld1 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi82 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
十月的皮皮3 小时前
C语言学习笔记20260606- 求月份天数三种写法
c语言·笔记·学习
搬砖魁首3 小时前
基础能力系列 - 多线程2 - 条件变量
c++·rust·条件变量·原子类型·线程同步互斥
youngerwang3 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
chase_my_dream3 小时前
C++ + SLAM 高频面试问题整理
开发语言·c++·面试
想要成为糕糕手4 小时前
前端必修课:JavaScript 数组与数据结构底层逻辑全解析
javascript·数据结构·面试
牛油果子哥q4 小时前
【C++ STL string 】C++ STL string 终极精讲:底层原理、内存机制、全套API、深浅拷贝、易错坑点与工程实战规范
数据库·c++