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

[算法] 结点K个一组的链表反转(hard)

文章目录

    • 1. 题目解析
    • 2. 讲解原理
    • 3. 编码实践

下面我们来分享一道简单的题目 -> 结点K个一组的链表反转(hard)

1. 题目解析

给你链表的头节点 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]

因此, 说白了, 就是给你一串链表, 然后要求你k个节点一组然后将其反转即可.

2. 讲解原理

本质求解思路是模拟算法. 这里模拟的思路可能有所不同, 下面提供一种模拟思路.

模拟策略:
1. 先求需要逆序多少组.
2. 重复n组长度为k的链表逆序.

下面解释几个问题:

  • 为什么要先求出需要逆序多少组?
    因为我们在处理链表的时候是对该节点是否要头插是不确定的, 比如示例2当中, 如果cur = 2, 则需要头插, 如果cur = 4, 则不能头插.
  • 如何求需要逆置多少组?
    很简单, 逆置组数 = 链表节点数量 / k.
  • 对于一组链表如何进行逆置?
    很简单, 新建一个虚拟节点, 然后挨个头插即可.

3. 编码实践

编码的难点: 编码的唯一难点在于, 在这个过程中会出现多个指针来回使用的情况, 需要搞清楚各个指针的作用以及逻辑.

/**
 * 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) {
        // 1. 先求出链表需要逆序多少组? 
        int size = 0;
        ListNode* cur = head;
        while(cur)
        {
            size += 1;
            cur = cur->next;
        }
        int n = size / k; 

        // 2. 逆序链表
        cur = head;
        ListNode* newHead = new ListNode;
        ListNode* prev = newHead;
        for(int i = 0; i < n; i++)
        {
            ListNode* temp = cur; 
            for(int j = 0; j < k; j++)
            {
                ListNode* next = cur->next;
                
                cur->next = prev->next;
                prev->next = cur;

                cur = next;
            }
            prev = temp;
        }

        // 3. 添加无需逆置的可能存在的剩余链表部分
        if(cur) prev->next = cur;

        // 4. 释放多余空间, 准备ret结果 
        prev = newHead->next;
        delete newHead;

        return prev;
    }
};

在这里插入图片描述

代码中各链表的含义:
newHead: 始终指向虚拟节点
prev: 指向头插的前一个节点
temp: 标记下一组头插的前一个节点
cur: 指向原链表, 用来遍历
next: 用来记录原链表cur指向的下一个节点, 方便cur回归原链表.

在这里插入图片描述
时间复杂度是: O(N)
空间复杂度: O(1)

相关文章:

  • 深入解析 TCP 协议【真题】
  • js-对象浅拷贝和深拷贝( B复制A,看B的值对比:都变为浅,一变一不变为深)
  • 5G技术与物联网融合:未来智慧城市的基石
  • Docker+Flask 实战:打造高并发微服务架构
  • ListView_GetIconBufferX函数和ListView_GetIconBufferY函数和RECT结构的关系
  • 【CXX】6.6 UniquePtr<T> — std::unique_ptr<T>
  • Windows安装milvus和图形化管理工具attu
  • 【webrtc debug tools】 rtc_event_log_to_text
  • 大数据面试之路 (一) 数据倾斜
  • 第一章:介绍Python编程-1.Python是什么
  • 2.2 企业级ESLint/Prettier规则定制
  • Excel两列和依次相减
  • AnyAnomaly: 基于大型视觉语言模型的零样本可定制视频异常检测
  • 中断机制及NVIC管理解析
  • Xavier 初始化:深度网络权重初始化的经典之作
  • Java小白-管理项目工具Maven(2)初识Maven
  • Cursor配置Golang开发环境
  • Java变量与常量
  • ubuntu 22.04 本地部署DeepSeek的Janus Pro
  • BigFoot EventAlertMod lua
  • 长沙潮宗街内“金丝楠木老屋文旅博物馆”起火:明火已扑灭,无伤亡
  • 国家主席习近平会见斯洛伐克总理菲佐
  • 央行最新报告:积极落地5月推出的一揽子金融政策,促进经济供需平衡、物价合理回升
  • 央行:货币与物价的关系受多重因素影响,提振物价的关键在于扩大有效需求
  • 赵作海因病离世,妻子李素兰希望过平静生活
  • 马上评丨行人转身相撞案:走路该保持“安全距离”吗