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

【算法面试必刷】25. K 个一组翻转链表

目录

题目

题目链接

思路

复杂度

代码


题目

给你链表的头节点head,每k个节点一组进行翻转,请你返回修改后的链表。

k是一个正整数,它的值小于或等于链表的长度。如果节点总数不是k的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

题目链接

25. K 个一组翻转链表 - 力扣(LeetCode)https://leetcode.cn/problems/reverse-nodes-in-k-group/description/?envType=study-plan-v2&envId=top-100-liked

思路

  1. 计算链表长度:首先遍历一次链表,得到总节点数length

  2. 确定组数:需要翻转的组数为length / k,因为最后一组如果不足k个节点则不翻转。

  3. 逐组翻转

    • 对于每一组,使用头插法将组内节点顺序反转。

    • 初始时,prev指向当前组的前一个节点(第一组前是虚拟头节点),curr指向组的第一个节点。

    • 在组内进行k-1次操作:每次将curr的下一个节点(即next)移动到prev的后面,这样逐步将后面的节点提到前面,实现反转。

    • 例如,对于链表1->2->3->4k=3,第一组为1-2-3

      • 第一次操作:将2移到prev后,得到2->1->3

      • 第二次操作:将3移到prev后,得到3->2->1

    • 一组翻转完成后,prev移动到当前组的最后一个节点(即原来的第一个节点),curr移动到下一组的第一个节点,继续下一组。

  4. 返回结果:虚拟头节点的next即为新链表的头节点。

复杂度

  • 时间复杂度O(n),其中n为链表长度。需要遍历一次链表计算长度,然后对每组进行翻转,每组内操作次数为k-1,总组数为n/k,因此总操作次数约为n + (n/k)*(k-1) = 2n - n/k,仍为线性时间。

  • 空间复杂度O(1),只使用了常数个额外指针,没有使用递归栈或额外数组。

代码

/** * 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* reverseKGroup(ListNode* head, int k) { // 创建一个虚拟头节点,方便处理边界情况 ListNode* dummy = new ListNode(0); dummy->next = head; // 虚拟头节点指向原链表头 ListNode* prev = dummy; // prev指向当前待翻转组的前一个节点 ListNode* curr = head; // curr指向当前组的第一个节点 ListNode* next; // 临时指针,用于保存要移动的节点 // 第一步:计算链表长度 int length = 0; ListNode* temp = head; // 临时指针,避免修改head while (temp) { length++; temp = temp->next; } // 第二步:循环处理每一组,组数为 length / k for (int i = 0; i < length / k; i++) { // 对当前组进行翻转,组内有k个节点,需要将后k-1个节点依次移到组首 for (int j = 0; j < k - 1; j++) { // 将curr的下一个节点(即要移动的节点)保存到next next = curr->next; // 将curr的next指向next的下一个节点,跳过next curr->next = next->next; // 将next插入到prev之后(即组首位置) next->next = prev->next; prev->next = next; // 注意:此时prev不变,curr也不变,但组内顺序已经变化 } // 当前组翻转完成后,移动prev和curr到下一组 prev = curr; // prev指向当前组的最后一个节点(翻转后成为组尾) curr = prev->next; // curr指向下一组的第一个节点 } // 返回新链表的头节点(虚拟头节点的下一个) return dummy->next; } };
http://www.jsqmd.com/news/473619/

相关文章:

  • SD卡/TF卡电源波动防护:从硬件设计到系统级稳定供电方案
  • Linux 0.11 进程状态变迁的日志追踪与性能分析实践
  • Blender3mfFormat插件全方位指南:3D打印工作流的革新方案
  • 跨平台分子动力学软件部署实战:从GROMACS、PACKMOL到VMD
  • 从局部对比度到注意力机制:ALCNet如何革新红外小目标检测
  • 经典IC(1):555定时器的三种工作模式与应用电路解析
  • 从Excel到地图:Arcmap坐标点导入实战与避坑指南
  • 2024年AI原生应用必备:上下文理解最佳实践
  • ETH-01串口以太网模块的TCP监听实战指南
  • MATLAB 2021a离线部署MinGW64编译器的完整指南
  • DownKyi:5大创新引擎破解B站视频本地化难题
  • Blender资产库实战:从标记到调用的高效工作流
  • 双目立体视觉(2)- ZED2双目相机实战应用指南
  • 揭秘:Prompt、Token与Completions在AI对话中的核心作用
  • 新手福音:在快马平台上手把手教你玩转Ollama本地AI模型
  • 从Eclipse到Xilinx SDK:揭秘FPGA软件开发环境的构建与高效上手
  • 在Cursor编辑器中配置Vue项目的ESLint自动修复脚本,告别代码规范引发的报错困扰
  • 从[NCTF2019]SQLi 1 到实战:基于REGEXP的布尔盲注自动化脚本设计与优化策略
  • 插件框架构建:面向Unity开发者的游戏功能扩展解决方案
  • Xilinx FPGA存储资源实战:移位寄存器、BRAM与URAM的高效应用
  • Visual Studio编码冲突实战:彻底解决warning C4819与代码页936的字符编码问题
  • 如何用Python调用阿里云的Qwen模型
  • 鸿蒙图片裁剪实战:从基础矩形到创意形状的完整指南
  • MATLAB实战:高斯与椒盐噪声的针对性滤波策略及效果可视化对比
  • DISC性格测评:解锁职场高效沟通的四大行为密码
  • Blender动捕数据bvh与fbx模型动作映射实战指南
  • 从并网到锁相:深入解析DQ坐标轴锁相环(PLL)的相位同步原理
  • 【技术解析】SENet中的SE Block:从图像到推荐的动态特征权重魔法
  • STM32CubeMX实战:ADC多通道+DMA循环传输的工程化配置与调试
  • BEVfusion复现避坑指南:从环境配置到可视化,手把手解决常见报错