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

【Leetcode 每日一题】25. K 个一组翻转链表

25. K 个一组翻转链表

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

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

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

示例 1:

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

示例 2:

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

提示:

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

进阶:你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?

解析:

将链表分成若干组,每组包含k个节点,然后对每组内的节点进行反转,同时保持组与组之间的相对顺序不变。解决办法的思路是首先创建一个虚拟头节点来简化头节点操作,然后遍历链表,每次检查是否有至少k个节点,如果有,则使用一个辅助函数来反转这k个节点,接着将反转后的节点组重新连接到原链表中,最后返回新链表的头节点。这个过程需要在每次反转后更新指针,以确保链表的连续性和正确性。

代码:

/**
 * 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:
    // 定义一个pair,用于存储反转链表的头尾节点
    pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail){
        ListNode* prev = tail->next; // 初始化prev为tail的下一个节点,即反转后的第一个节点
        ListNode* p = head; // 初始化p为当前处理的节点,从头节点开始
        while (prev != tail){ // 遍历链表直到prev等于tail,即到达需要反转的链表的末尾
            ListNode* nex = p->next; // 保存p的下一个节点
            p->next = prev; // 反转p的next指针,指向prev
            prev = p; // 移动prev到p的位置
            p = nex; // 移动p到下一个节点
        }
        return {tail,head}; // 返回反转后的链表头尾节点
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* hair = new ListNode(0); // 创建一个虚拟头节点,方便处理原链表头
        hair->next = head; // 虚拟头节点的next指向原链表头
        ListNode* pre = hair; // 初始化pre为虚拟头节点,用于追踪反转组的前一个节点

        while(head){ // 遍历链表直到到达末尾
            ListNode* tail = pre; // 初始化tail为pre,即当前组的起始节点
            for(int i=0;i<k;++i){ // 检查是否有足够的节点进行反转
                tail = tail->next; // 移动tail指针,寻找当前组的尾节点
                if(!tail){ // 如果tail为空,说明没有足够的节点进行反转
                    return hair->next; // 返回原链表头
                }
            }

            ListNode* nex = tail->next; // 保存tail的下一个节点,即下一组的头节点
            tie(head,tail) = myReverse(head, tail); // 调用myReverse反转当前组
            pre->next = head; // 将反转后的头节点连接到pre的后面
            tail->next = nex; // 将反转后的尾节点连接到下一组的头节点
            pre = tail; // 更新pre为当前组的尾节点,即下一组的起始节点
            head = tail->next; // 更新head为下一组的头节点
        }
        return hair->next; // 返回新链表的头节点
    }
};


http://www.kler.cn/a/413774.html

相关文章:

  • 通信网络安全分层及关键技术解决
  • elasticsearch的索引模版使用方法
  • docker部署nginx,并配置SSL证书
  • 扫振牙刷设计思路以及技术解析
  • pytest 通过实例讲清单元测试、集成测试、测试覆盖率
  • 深度神经网络模型压缩学习笔记二:离线量化算法和工具、实现原理和细节
  • 动态加载Jar包引发的“java.util.zip.ZipException: invalid distance too far back”
  • 定制独立站系统需要哪些技术支持?
  • 不间断电源 (UPS) 对现代技术可靠性的影响
  • 机器学习之DeepMind推出的DreamerV3
  • 代码随想录-笔记-其五
  • 基于springboot的登录校验
  • 通信网络安全
  • Java对象与XML互相转换(xstream)
  • 本地化部署 私有化大语言模型
  • ABAP OOALV模板
  • Android中ByteBuffer内存池设计示例
  • 23种设计模式之外观模式
  • linux添加附加磁盘
  • CFD 在生物反应器放大过程中的作用
  • 拍立淘按图搜索实战化,拍立淘API接口参数说明
  • 在 Ubuntu 上部署 MediaWiki 开源维基平台
  • Jetpack业务架构(ViewModel)
  • Linux系统之iotop命令的基本使用
  • 【EI会议征稿通知 | 往届均已见刊检索】第四届电子信息工程、大数据与计算机技术国际学术会议(EIBDCT 2025)
  • 分类预测 | Matlab实现GA-XGBoost分类预测