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)

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


小结

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

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

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

相关推荐
Fcy6486 小时前
算法基础详解(三)前缀和与差分算法
算法·前缀和·差分
kvo7f2JTy6 小时前
基于机器学习算法的web入侵检测系统设计与实现
前端·算法·机器学习
List<String> error_P6 小时前
蓝桥杯最后几天冲刺:暴力大法(一)
算法·职场和发展·蓝桥杯
Hou'7 小时前
从0到1的C语言传奇之路
c语言·开发语言
Tanecious.7 小时前
蓝桥杯备赛:Day6-B-小紫的劣势博弈 (牛客周赛 Round 85)
c++·蓝桥杯
迈巴赫车主7 小时前
蓝桥杯3500阶乘求和java
java·开发语言·数据结构·职场和发展·蓝桥杯
流云鹤7 小时前
Codeforces Round 1090 (Div. 4)
c++·算法
小菜鸡桃蛋狗7 小时前
C++——string(上)
开发语言·c++
wljy17 小时前
第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(个人见解,已完结)
c语言·c++·算法·蓝桥杯·stl
高一要励志成为佬8 小时前
【数据结构】算法复杂度
数据结构