链表【3】

news2024/11/16 22:48:00

在这里插入图片描述

文章目录

    • 🐳23. 合并 K 个升序链表
      • 🐟题目
      • 🐬算法原理
      • 🐠代码实现
    • 🐷25. K 个一组翻转链表
      • 🐖题目
      • 🐽算法原理
      • 🍧代码实现

🐳23. 合并 K 个升序链表

🐟题目

题目链接:23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[] 

提示:

  • k == lists.length
  • 0 <= k <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[i]升序 排列
  • lists[i].length 的总和不超过 10^4

🐬算法原理

解法一:优先级队列(小根堆)

这里用优先级队列,先将k个链表的头节点全部放入这个小根堆当中,然后每次取出对顶元素插入到新链表当中,插入完毕之后,再将这个节点的下一个节点加入到小根堆当中。

时间复杂度:O(nk*logK)

堆向下调整的时间复杂度为O(logN),有k个链表,每个链表有n,所以复杂度为O(nk*logK)

解法二:分治(递归)

用归并排序的思路,归并排序将数组两两拆分再合并,而这里只是将链表拆分再合并。

直接看图,将递归看作黑盒,不管怎么样,它一定能完成我们要求的任务

image-20231204215753409

时间复杂度:O(nk*logK)

这里将链表两两拆分,就和二叉树一样,每层执行一次合并操作,相当于合并树的高度次,也就是logK,这里有k个链表,每个链表n个节点,所以复杂度为O(nk*logK)

🐠代码实现

解法一:优先级队列

/**
 * 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:

    struct cmp
    {
        bool operator()(const ListNode* l1 , const ListNode* l2)
        {
            return l1->val > l2->val;
        }
    };

    ListNode* mergeKLists(vector<ListNode*>& lists)
    {
        //优先级队列默认大根堆,写一个仿函数
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;

        //头节点进小根堆
        for(auto l : lists)
        {
            if(l)   heap.push(l);
        }

        //合并
        ListNode* ret = new ListNode(0);
        ListNode* prev = ret;
        while(!heap.empty())
        {
            ListNode* t = heap.top();
            heap.pop();
            prev->next = t;
            prev = t;
            if(t->next) heap.push(t->next);
        }
        prev = ret->next;
        delete ret;
        return prev;


    }
};

分治

/**
 * 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* mergeKLists(vector<ListNode*>& lists)
    {
        return merge(lists,0,lists.size()-1);
    }

    ListNode* merge(vector<ListNode*>& lists, int left, int right)
    {
        if(left > right)    return nullptr;
        if(left == right)   return lists[left];
        
        int mid = (left+right) >> 1;
        ListNode* l1 = merge(lists,left,mid);
        ListNode* l2 = merge(lists,mid+1,right);

        return mergeTwoList(l1,l2);
    }

    ListNode* mergeTwoList(ListNode* l1, ListNode* l2)
    {
        if(l1 == nullptr)  return l2;
        if(l2 == nullptr)  return l1;

        //合并链表
        ListNode head;
        ListNode* cur1 = l1, *cur2 = l2, *prev = &head;
        head.next = nullptr;

        while(cur1 && cur2)
        {
            if(cur1->val <= cur2->val)
            {
                prev->next = cur1;
                prev = prev->next;
                cur1 = cur1->next;
                
            }
            else
            {
                prev->next = cur2;
                prev = prev->next;
                cur2 = cur2->next;
            }
        }
        if(cur1) prev->next = cur1;
        if(cur2) prev->next = cur2;
        return head.next;
    }
};

运行结果:

image-20231204215010236

🐷25. K 个一组翻转链表

🐖题目

题目链接:25. K 个一组翻转链表

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

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

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

示例 1:

img

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

示例 2:

img

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

提示:

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

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

🐽算法原理

这里还是模拟,分为两步走:

  1. 求出要逆序多少组,group = n/k
  2. 重复group次逆置操作(头插)

🍧代码实现

模拟:

/**
 * 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)
    {
        int n = 0;
        ListNode* cur = head;
        while(cur)
        {
            n++;
            cur = cur->next;
        }

        int group = n/k;

        ListNode* newHead = new ListNode(0);
        ListNode* prev = newHead;
        cur = head;
        while(group--)
        {
            //记录要头插的位置
            ListNode* tmp = cur;
            for(int i=0; i<k; i++)
            {
                ListNode* next = cur->next;
                cur->next = prev->next;
                prev->next = cur;
                cur = next;
            }
            prev = tmp;
        }

        //接上不需要翻转的节点
        prev->next = cur;
        cur = newHead->next;
        delete newHead;
        return cur;
    }
};

运行结果:

image-20231204221645035

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1284002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sentinel基础知识

Sentinel基础知识 资源 1、官方网址&#xff1a;https://sentinelguard.io/zh-cn/ 2、os-china: https://www.oschina.net/p/sentinel?hmsraladdin1e1 3、github: https://github.com/alibaba/Sentinel 一、软件简介 Sentinel 是面向分布式服务架构的高可用流量防护组件…

Unity 关于SetParent方法的使用情况

在设置子物体的父物体时&#xff0c;我们使用SetParent再常见不过了。 但是通常我们只是使用其中一个语法&#xff1a; public void SetParent(Transform parent);使用改方法子对象会保持原来位置&#xff0c;跟使用以下方法效果一样&#xff1a; public Transform tran; ga…

【数值计算方法(黄明游)】函数插值与曲线拟合(二):Newton插值【理论到程序】

​ 文章目录 一、近似表达方式1. 插值&#xff08;Interpolation&#xff09;2. 拟合&#xff08;Fitting&#xff09;3. 投影&#xff08;Projection&#xff09; 二、Lagrange插值1. 拉格朗日插值方法2. Lagrange插值公式a. 线性插值&#xff08;n1&#xff09;b. 抛物插值&…

UDS 诊断报文格式

文章目录 网络层目的N_PDU 格式诊断报文的分类&#xff1a;单帧、多帧 网络层目的 N_PDU(network protocol data unit)&#xff0c;即网络层协议数据单元 网络层最重要的目的就是把数据转换成符合标准的单一数据帧&#xff08;符合can总线规范的&#xff09;&#xff0c;从而…

原生横向滚动条 吸附 页面底部

效果图 /** 横向滚动条 吸附 页面底部 */ export class StickyHorizontalScrollBar {constructor(options {}) {const { el, style } optionsthis.createScrollbar(style)this.insertScrollbar(el)this.setScrollbarSize()this.onEvent()}/** 创建滚轴组件元素 */createS…

【踩坑】解决maven的编译报错Cannot connect to the Maven process. Try again later

背景 新公司新项目, 同事拷给我maven的setting配置文件, 跑项目编译发现maven报 Cannot connect to the Maven process. Try again later. If the problem persists, check the Maven Importing JDK settings and restart IntelliJ IDEA 虽然好像不影响, 项目最终还是能跑起来…

计算机组成学习-存储系统总结

复习本章时&#xff0c;思考以下问题&#xff1a; 1)存储器的层次结构主要体现在何处&#xff1f;为何要分这些层次&#xff1f;计算机如何管理这些层次&#xff1f;2)存取周期和存取时间有何区别&#xff1f;3)在虚拟存储器中&#xff0c;页面是设置得大一些好还是设置得小一…

视频剪辑转码:mp4批量转成wmv视频,高效转换格式

在视频编辑和处理的领域&#xff0c;转换格式是一项常见的任务。在某些编辑和发布工作中&#xff0c;可能需要使用WMV格式。提前将素材转换为WMV可以节省在编辑过程中的时间和精力。从MP4到WMV的批量转换&#xff0c;不仅能使视频素材在不同的平台和设备上得到更好的兼容性&…

JavaScript基础—for语句、循环嵌套、数组、操作数组、综合案例—根据数据生成柱形图、冒泡排序

版本说明 当前版本号[20231129]。 版本修改说明20231126初版20231129完善部分内容 目录 文章目录 版本说明目录JavaScript 基础第三天笔记for 语句for语句的基本使用循环嵌套倒三角九九乘法表 数组数组是什么&#xff1f;数组的基本使用定义数组和数组单元访问数组和数组索引…

centos7 设置静态ip

文章目录 设置VMware主机设置centos7 设置 设置VMware 主机设置 centos7 设置 vim /etc/sysconfig/network-scripts/ifcfg-ens33重启网络服务 service network restart检验配置是否成功 ifconfig ip addr

爬虫概念、基本使用及一个类型和六个方法(一)

目录 一、爬虫简介 1.什么是爬虫 2.爬虫的核心 3.爬虫的用途 4.爬虫的分类 5.反爬手段 二、Urllib基本使用 1.导入我们需要的包 2.定义一个url 3.模拟浏览器向服务器发送请求 4.获取响应中的页面的源码 5.打印数据 三、一个类型和六个方法 1.定义url&#xff0c;并…

BFS求树的宽度——结合数组建树思想算距离

二叉树最大宽度 https://leetcode.cn/problems/maximum-width-of-binary-tree/description/ 1、考虑树的宽度一定是在一层上的所以进行BFS&#xff0c;树的BFS不建议直接使用队列&#xff0c;每次add/offer然后poll/remove&#xff0c;这样子层级关系不好显示。我们可以定义…

深入解析常见的软件架构模式

在软件开发领域&#xff0c;选择合适的架构模式对于项目的可维护性和扩展性至关重要。本文将深入探讨常见的软件架构模式&#xff0c;包括MVC、MVP、MVVM、MVVM-C以及VIPER。 1. MVC&#xff08;Model-View-Controller&#xff09; MVC 是一种经典的软件架构模式&#xff0c;将…

电子学会C/C++编程等级考试2022年06月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:公共子序列 我们称序列Z = < z1, z2, ..., zk >是序列X = < x1, x2, ..., xm >的子序列当且仅当存在 严格上升 的序列< i1, i2, ..., ik >,使得对j = 1, 2, ... ,k, 有xij = zj。比如Z = < a, b, f, c &…

MYSQL练题笔记-聚合函数-即时食物配送

我做完上一道题&#xff0c;决定总结一下了&#xff0c;因为现在还是没有一个我认为好的思路去构造语句&#xff0c;这里开始试一试新的思路。果然想要好一点的时候&#xff0c;总是像便秘一下&#xff0c;真的想拉&#xff0c;但是真的难拉啊 一、题目相关内容 1&#xff09…

软件测试HR总结的软件测试常见面试题

一、测试流程是什么样的&#xff1f; 1.产品确定需求后&#xff0c;邀请项目经理&#xff0c;开发&#xff0c;测试等人员参加需求评审会&#xff1b; 2.评审结束后开发根据需求文档和接口文档开发&#xff0c;测试制定测试计划和编写手工测试用例&#xff0c;测试脑图&#xf…

给 Web 前端工程师看的用 Rust 开发 wasm 组件实战 | 京东云技术团队

什么是wasm组件&#xff1f; wasm 全称 WebAssembly&#xff0c;是通过虚拟机的方式&#xff0c;可以在服务端、客户端如浏览器等环境执行的二进制程序。他有速度快、效率高、可移植的特点。 对我们 Web 前端工程最大的好处就是可以在浏览器端使用二进制程序处理一些计算量大…

STM32串口接收不定长数据(空闲中断+DMA)

玩转 STM32 单片机&#xff0c;肯定离不开串口。串口使用一个称为串行通信协议的协议来管理数据传输&#xff0c;该协议在数据传输期间控制数据流&#xff0c;包括数据位数、波特率、校验位和停止位等。由于串口简单易用&#xff0c;在各种产品交互中都有广泛应用。 但在使用串…

华为云云绘本第一期:童话奇迹原来是你

点此进入官网&#xff0c;专家1对1&#xff1a;应用身份管理服务OneAccess_华为云IDaaS-华为云

视频剪辑自动化:批量色调调整技巧,让工作更轻松

随着数字媒体技术的不断发展&#xff0c;视频剪辑已经成为许多行业不可或缺的一部分。然而&#xff0c;对于许多剪辑师来说&#xff0c;色调调整是视频剪辑过程中一项繁琐且耗时的任务。如何提高工作效率&#xff0c;本文讲解云炫AI智剪如何批量调整色调技巧&#xff0c;让视频…