当前位置: 首页 > news >正文

Leetcode 107 旋转链表

1 题目

61. 旋转链表

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

示例 1:

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

示例 2:

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

提示:

  • 链表中节点的数目在范围[0, 500]
  • -100 <= Node.val <= 100
  • 0 <= k <= 2 * 109

2 代码实现

c++

/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* rotateRight(ListNode* head, int k) { if (head == nullptr || head -> next == nullptr || k == 0 ){ return head ; } int n = 1; ListNode* tail = head ; while (tail -> next != nullptr){ tail = tail -> next ; n++; } int step = k % n ; if (step == 0 ){ return head ; } tail -> next = head ; ListNode* new_tail = head ; for (int i = 0 ; i < n - step - 1 ; ++i){ new_tail = new_tail -> next ; } ListNode* new_head = new_tail -> next ; new_tail -> next = nullptr ; return new_head; } };

js

/** * Definition for singly-linked list. * function ListNode(val, next) { * this.val = (val===undefined ? 0 : val) * this.next = (next===undefined ? null : next) * } */ /** * @param {ListNode} head * @param {number} k * @return {ListNode} */ var rotateRight = function(head, k) { if (head == null || head.next == null || k == 0){ return head ; } let n = 1 ; let tail = head ; while(tail.next != null){ tail = tail.next ; n++; } tail.next = head ; let step = k % n ; let new_tail = head ; for(let i = 0 ; i < n - step - 1 ; i++){ new_tail = new_tail.next ; } const new_head = new_tail.next ; new_tail.next = null ; return new_head; };

思考

这道题目我觉得k就是一个“旋转”操作的执行次数,比较难的地方就是尾部的结点要怎么又接回来。

我大概的思路就是建立一个虚拟头结点dummy,cur从head 出发 ,然后dummy -> next = cur -> next ;这么一直往后“旋转”连接,直到cur -> next 是空的了,再把原来的头结点接回来?

不知道怎么写,需要看看cpp实现的题解,我怎么想都觉得这个新的head写法有点麻烦。

题解

解题思路分析

首先要明确一个关键点:如果链表长度为n,那么向右移动k个位置等价于向右移动k % n个位置(因为移动n个位置后链表会回到原样)。这能避免k过大时的无效操作。

解决这个问题的核心步骤:

  1. 处理特殊情况(空链表、k=0、链表只有 1 个节点),直接返回原链表;
  2. 遍历链表,统计节点总数n,同时找到链表的尾节点;
  3. 计算有效移动步数step = k % n,如果step=0直接返回原链表;
  4. 将链表首尾相连,形成环形链表;
  5. 找到新的尾节点(原链表的第n-step个节点),断开环形链表,新的头节点就是尾节点的下一个节点。

C++ 完整实现代码

#include <iostream> using namespace std; // 定义链表节点结构 struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; class Solution { public: ListNode* rotateRight(ListNode* head, int k) { // 特殊情况:空链表、只有一个节点、k=0,直接返回原链表 if (head == nullptr || head->next == nullptr || k == 0) { return head; } // 第一步:统计链表节点数n,并找到尾节点tail int n = 1; // 至少有一个节点(head非空) ListNode* tail = head; while (tail->next != nullptr) { tail = tail->next; n++; } // 第二步:计算有效移动步数(k可能远大于n) int step = k % n; if (step == 0) { // 移动n的倍数,链表不变 return head; } // 第三步:将链表连成环形(尾节点指向头节点) tail->next = head; // 第四步:找到新的尾节点(距离原头节点n-step-1步) ListNode* new_tail = head; for (int i = 0; i < n - step - 1; i++) { new_tail = new_tail->next; } // 第五步:新的头节点是新尾节点的下一个节点,断开环形链表 ListNode* new_head = new_tail->next; new_tail->next = nullptr; return new_head; } }; // 辅助函数:打印链表 void printList(ListNode* head) { while (head != nullptr) { cout << head->val << " "; head = head->next; } cout << endl; } // 测试用例 int main() { // 示例1:head = [1,2,3,4,5], k=2 ListNode* head1 = new ListNode(1); head1->next = new ListNode(2); head1->next->next = new ListNode(3); head1->next->next->next = new ListNode(4); head1->next->next->next->next = new ListNode(5); Solution s; ListNode* res1 = s.rotateRight(head1, 2); cout << "示例1输出:"; printList(res1); // 预期输出:4 5 1 2 3 // 示例2:head = [0,1,2], k=4 ListNode* head2 = new ListNode(0); head2->next = new ListNode(1); head2->next->next = new ListNode(2); ListNode* res2 = s.rotateRight(head2, 4); cout << "示例2输出:"; printList(res2); // 预期输出:2 0 1 return 0; }

代码关键部分解释

  1. 特殊情况处理:避免无意义的计算,比如空链表、单节点链表无需旋转,直接返回;
  2. 统计节点数 + 找尾节点:这一步是为了后续计算有效步数,同时为连成环形链表做准备;
  3. 有效步数计算k % n是核心优化,比如示例 2 中k=4n=3,有效步数是1(4%3=1),等价于向右移动 1 个位置;
  4. 环形链表处理:将尾节点指向头节点,这样旋转时无需反复遍历,只需找到新的头尾节点即可;
  5. 找新的头尾节点
    • 新尾节点位置:原链表的第n-step-1个节点(比如示例 1 中n=5step=2,新尾节点是第5-2-1=2个节点,即值为 3 的节点);
    • 新头节点是新尾节点的下一个节点(示例 1 中是 4),最后断开环形链表(新尾节点的 next 置空)。

总结

  1. 核心优化点:用k % n减少无效旋转,避免k过大时的性能问题;
  2. 关键技巧:将链表连成环形,通过找节点位置直接确定新的头尾,无需逐次旋转;
  3. 步骤逻辑:统计长度→算有效步数→连环形→找新头尾→断环形。

这种方法的时间复杂度是 O (n)(只遍历链表两次),空间复杂度是 O (1)(只使用了几个指针变量),是最优的解法。

3 小结

变成环形以后再求解,然后断链,我觉得虽然我们走测试用例的时候是这么想的,但我实际却没有用这样成环又断链的办法在做,见多识广吧,我个人感受是见过这个做法就知道,没见过就不知道,会者不难,难者不会,也不必太担忧。

  1. 先统计长度是链表题的常见套路很多链表题目,只要涉及 “旋转”“倒数第 k 个”“环” 等,都需要先知道链表长度,这一步往往能带来后续的巨大简化。

  2. k 可能非常大,必须用 k % n 来减少无效操作题目给的 k 可以达到 2×10^9,如果不做取模,直接模拟肯定超时。取模后问题规模瞬间缩小到链表长度范围内。

  3. 成环操作让 “旋转” 变成了 “找节点 + 断链”把链表首尾相连后,旋转 k 次等价于在环中找到新的尾节点,然后断开环。这个思路非常巧妙,也非常高效。

  4. 新尾节点的位置公式 n - step - 1 是关键理解这个公式的推导过程后,整个题就变得非常清晰:新尾节点就是原链表中 “倒数第 step+1 个节点”。

http://www.jsqmd.com/news/304095/

相关文章:

  • 数据工程新范式:基于 NoETL 语义编织实现自助下钻分析
  • 2026年 吸塑品牌实力推荐榜:专业厂家深度解析,涵盖厚片吸塑、精密吸塑、大型吸塑制品的优质品牌全景测评
  • 2026四川护栏网优质产品推荐榜
  • PWR电源控制
  • 基于容器化的边缘计算网关应用部署实践:Python+MQTT
  • 计算机毕业设计springboot机票订购系统的设计与实现 基于Spring Boot框架的在线机票预订系统开发与实践 利用Spring Boot实现的机票预订平台设计与应用
  • 计算机毕业设计springboot智慧乡村服务平台 基于Spring Boot框架的智慧乡村综合服务平台设计与实现 Spring Boot驱动的智慧乡村服务系统开发与应用
  • 震惊!腾讯企业邮箱在梅州竟有这样的服务商内幕!
  • 全球主流进口电子秤制造商综合实力全景对比与评析
  • 2026年 塑料板材厂家推荐排行榜:ABS/PS/PP/PE/PET/PVC板材,精选高韧性耐腐蚀工程塑料板材优质品牌!
  • 成都附近打印机出租公司、成都附近打印机租赁、成都附近打印机租赁公司、成都周边打印机出租、成都周边打印机租赁、成都彩色打印机出租选择指南
  • 核心技术大起底:看这几家真空石墨炉/碳管炉厂家如何掌握加热体命脉
  • 车铣复合加工机床品牌推荐:用户口碑与型号全攻略
  • 【JavaWeb】HttpServletRequest_获得请求中的键值对参数相关API - 实践
  • 卫生初中级职称考试题库深度测评 在职备考高性价比之选
  • Sufficient 英文单词学习
  • INVICTA BLz05-2/4 底座安装式电动振动电机
  • 2026铜接触网线市场增长:电气化铁路与城市轨道交通中的关键角色
  • 强烈安利继续教育TOP10AI论文平台:写论文不再难
  • ICML2025|宁波东方理工大学刘野,陈云天:DragSolver:用于真实汽车风阻系数估计的多尺度Transformer方法
  • PRF | 宾州州立、南科大杨翔、张雯等:粗糙壁湍流的低维建模新范式
  • Infoseek 媒介投放系统技术实现:基于与辉同行风波的风险防控架构设计
  • 疆鸿智能MODBUS TCP转PROFIBUS:网关智构精密组装新脉络
  • 2026年评价高的防静电地板公司推荐:水泥纤维网络架空地板、活动架空地板、玻璃防静电地板、硫酸钙防静电地板、通风防静电地板选择指南
  • 记重要需严格
  • 2026年评价高的耐火砖公司推荐:耐火材料推荐/耐火材料电话/耐火砖供应厂家/耐火砖厂商/耐火砖厂家/耐火砖厂家电话/选择指南
  • 计算机毕业设计springboot协同过滤的就业系统的设计与实现 基于Springboot框架的就业推荐系统设计与实现 Springboot协同过滤技术在就业平台中的应用与开发
  • 2026美团代运营公司实力榜:这5家真正懂外卖流量!三十六行网络科技(阜阳分公司)领跑内容与策略赛道
  • JWT(JSON Web Tokens )简洁说明
  • 计算机毕业设计springboot校园学生健康管理与服务系统 基于Spring Boot的校园学生健康管理系统设计与开发 Spring Boot框架下的校园学生健康管理服务平台构建