LeetCode 算法: 合并 K 个升序链表 c++

news2024/11/22 16:51:44

原题链接🔗:合并 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 <= 104
  • 0 <= lists[i].length <= 500
  • -104 <= lists[i][j] <= 104
    lists[i] 按 升序 排列
    lists[i].length 的总和不超过 104

题解

分支法

  1. 解题思路:
  1. ListNode结构体:定义了一个链表节点,包含一个整数值val和一个指向下一个节点的指针next

  2. Solution类:包含合并K个链表的逻辑。

    • mergeKLists函数:接收一个链表指针的向量,调用merge函数进行合并。
    • merge函数:递归地将链表列表分成两半,直到每半只有一个链表,然后调用mergeTwoLists函数合并两个链表。
    • mergeTwoLists函数:合并两个已排序的链表,返回合并后的链表头节点。
  3. 辅助函数

    • createList函数:根据提供的整数列表创建一个新的链表。
    • deleteList函数:释放链表占用的内存。
    • printList函数:打印链表的元素。
  4. main函数:程序的入口点,用于测试Solution类的mergeKLists函数。

    • 创建了三个链表l1l2l3
    • 将这些链表放入一个向量lists中。
    • 使用Solution类的实例调用mergeKLists函数,合并链表。
    • 打印合并后的链表。
    • 释放合并后链表的内存。

使用分治法来合并链表。merge函数递归地将链表列表分成两半,直到每个子问题只包含一个链表,然后使用mergeTwoLists函数将两个相邻的链表合并。这种方法的时间复杂度为O(N log K),其中N是所有链表中节点的总数,K是链表的数量。

  1. 复杂度:时间复杂度为O(N log K),空间复杂度时间复杂度为O(log K)
  2. c++ demo:
#include <iostream>
#include <vector>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

class Solution {
public:
    ListNode* mergeKLists(std::vector<ListNode*>& lists) {
        if (lists.empty()) return nullptr;
        return merge(lists, 0, lists.size() - 1);
    }

private:
    ListNode* merge(std::vector<ListNode*>& lists, int left, int right) {
        if (left == right) return lists[left];
        int mid = left + (right - left) / 2;
        ListNode* leftList = merge(lists, left, mid);
        ListNode* rightList = merge(lists, mid + 1, right);
        return mergeTwoLists(leftList, rightList);
    }

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode(0);
        ListNode* tail = dummy;
        while (l1 && l2) {
            if (l1->val < l2->val) {
                tail->next = l1;
                l1 = l1->next;
            }
            else {
                tail->next = l2;
                l2 = l2->next;
            }
            tail = tail->next;
        }
        tail->next = (l1) ? l1 : l2;
        return dummy->next;
    }
};

// 辅助函数,用于创建链表
ListNode* createList(std::initializer_list<int> values) {
    ListNode* head = new ListNode(0);
    ListNode* tail = head;
    for (auto value : values) {
        tail->next = new ListNode(value);
        tail = tail->next;
    }
    return head->next;
}

// 辅助函数,用于释放链表内存
void deleteList(ListNode* head) {
    while (head) {
        ListNode* temp = head;
        head = head->next;
        delete temp;
    }
}

// 测试函数
void printList(ListNode* head) {
    while (head) {
        std::cout << head->val << " -> ";
        head = head->next;
    }
    std::cout << "null" << std::endl;
}

int main() {
    // 测试用例
    ListNode* l1 = createList({ 1, 4, 5 });
    ListNode* l2 = createList({ 1, 3, 4 });
    ListNode* l3 = createList({ 2, 6 });

    std::vector<ListNode*> lists = { l1, l2, l3 };
    Solution solution;
    ListNode* mergedList = solution.mergeKLists(lists);

    printList(mergedList);

    // 释放合并后链表的内存
    deleteList(mergedList);

    return 0;
}
  • 输出结果:

1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6 -> null
在这里插入图片描述

分治法

分治法(Divide and Conquer)是一种算法设计范式,它通过将问题分解为更小的子问题来解决,然后递归地解决这些子问题,并将结果合并以形成原问题的解。这种方法通常用于可以自然地分解成相似子问题的问题,如排序算法(例如快速排序和归并排序)、矩阵乘法、乘法算法等。

分治法的关键步骤通常包括:

  1. 分解(Divide):将原问题分解为若干个规模较小的相同问题。
  2. 解决(Conquer):独立地解决这些子问题。如果子问题足够小,则可以直接求解。
  3. 合并(Combine):将子问题的解合并以形成原问题的解。

示例:归并排序

归并排序是分治法的一个经典例子。以下是使用分治法实现归并排序的步骤:

  1. 分解:将数组从中间分成两部分。
  2. 解决:递归地对这两部分进行归并排序。
  3. 合并:将排序好的两部分合并成一个有序数组。

下面是归并排序的 C++ 实现:

#include <iostream>
#include <vector>

void merge(std::vector<int>& arr, int l, int m, int r) {
    std::vector<int> temp(r - l + 1);
    int i = l, j = m + 1, k = 0;

    // 合并过程
    while (i <= m && j <= r) {
        if (arr[i] <= arr[j]) {
            temp[k++] = arr[i++];
        } else {
            temp[k++] = arr[j++];
        }
    }

    // 复制左边剩余元素
    while (i <= m) {
        temp[k++] = arr[i++];
    }
    // 复制右边剩余元素
    while (j <= r) {
        temp[k++] = arr[j++];
    }

    // 将临时数组的内容复制回原数组
    for (k = 0; k < temp.size(); k++) {
        arr[l + k] = temp[k];
    }
}

void mergeSort(std::vector<int>& arr, int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m); // 递归分解左边
        mergeSort(arr, m + 1, r); // 递归分解右边
        merge(arr, l, m, r); // 合并
    }
}

int main() {
    std::vector<int> arr = {38, 27, 43, 3, 9, 82, 10};
    int n = arr.size();

    mergeSort(arr, 0, n - 1);

    std::cout << "Sorted array:\n";
    for (int i : arr) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,mergeSort 函数是一个递归函数,它将数组分成更小的部分,直到每部分只有一个元素(这是最小的有序数组)。然后,merge 函数将这些有序数组合并成更大的有序数组,直到最终得到完全排序的数组。

分治法是解决许多算法问题的强大工具,它强调了递归和问题分解的重要性。

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

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

相关文章

Hugging Face Accelerate 两个后端的故事:FSDP 与 DeepSpeed

社区中有两个流行的零冗余优化器 (Zero Redundancy Optimizer&#xff0c;ZeRO)算法实现&#xff0c;一个来自DeepSpeed&#xff0c;另一个来自PyTorch。Hugging FaceAccelerate对这两者都进行了集成并通过接口暴露出来&#xff0c;以供最终用户在训练/微调模型时自主选择其中之…

Python | Leetcode Python题解之第191题位1的个数

题目&#xff1a; 题解&#xff1a; class Solution:def hammingWeight(self, n: int) -> int:ret 0while n:n & n - 1ret 1return ret

PAE:从潮流报告中提炼有效产品属性

本文将介绍PAE&#xff0c;一种用于包含 PDF格式的文本和图像的产品属性提取算法。目前大部分的方法侧重于从标题或产品描述中提取属性&#xff0c;或利用现有产品图像中的视觉信息。与之前的工作相比&#xff0c;PAE从潮流趋势报告的PDF文件中提取属性&#xff0c;提取的属性包…

ISO26262标准

什么是ISO26262&#xff1f; ISO 26262(国际功能安全标准)是一个涵盖整个汽车产品开发过程的汽车功能安全标准。ISO 26262继承或改编自工业自动化行业的安全要求标准IEC61508&#xff0c;但专门为汽车行业量身定制。最新版本是ISO26262-1:2018。 它包括诸如需求分析、安全分析…

一个简单的文件上传功能

代码如下&#xff1a; PostMapping("/upload")public ResponseEntity<String> handleFileUpload(RequestParam(value "uploadDirectory") String uploadDirectory,RequestParam("fileName") MultipartFile fileName) {try {// 确保文件不…

乱扔垃圾自动识别摄像头

如今&#xff0c;随着城市化进程的加快和人们生活水平的提高&#xff0c;环境保护和城市美观成为社会关注的焦点。乱扔垃圾问题长期困扰着城市管理者和居民&#xff0c;给城市环境卫生带来严重挑战。为了有效解决这一问题&#xff0c;乱扔垃圾自动识别摄像头应运而生&#xff0…

nvm-desktop window安装,支持动态切换nodejs版本

一、安装 nvm-desktop 概述 1 、卸载干净笔记的nodejs 和nodejs的环境变量 2、安装 nvm-desktop 软件 3、配置环境变量 4、测试功能 # 此时已安装完成 其他&#xff1a;常见nodejs的问题解决参考&#xff1a;官网 mac 安装教程 https://github.com/1111mp/nvm-desktop/blob/…

大模型微调实战之基于星火大模型的群聊对话分角色要素提取挑战赛:Task01:跑通Baseline

目录 0 背景1 环境配置1.1 下载包1.2 配置密钥1.3 测试模型 2 解决问题2.1 获取数据2.2 设计Prompt2.2 设计处理函数2.3 开始提取 附全流程代码 0 背景 Datawhale AI夏令营第二期开始啦&#xff0c;去年有幸参与过第一期&#xff0c;收获很多&#xff0c;这次也立马参与了第二…

基于Python的求职招聘管理系统【附源码】

摘 要 随着互联网技术的不断发展&#xff0c;人类的生活已经逐渐离不开网络了&#xff0c;在未来的社会中&#xff0c;人类的生活与工作都离不开数字化、网络化、电子化与虚拟化的数字技术。从互联网的发展历史、当前的应用现状和发展趋势来看&#xff0c;我们完全可以肯定&…

AI视界引擎 | ​基于 YOLOv8 和计算机视觉 CV 的实时识别系统!

本文来源公众号“AI视界引擎”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;​基于 YOLOv8 和计算机视觉 CV 的实时识别系统&#xff01; 技术进步和创新正在尽可能地推进作者的日常生活&#xff0c;但仍有很大一部分社会群体因为…

OverTheWire Bandit 靶场通关解析(中)

介绍 OverTheWire Bandit 是一个针对初学者设计的网络安全挑战平台&#xff0c;旨在帮助用户掌握基本的命令行操作和网络安全技能。Bandit 游戏包含一系列的关卡&#xff0c;每个关卡都需要解决特定的任务来获取进入下一关的凭证。通过逐步挑战更复杂的问题&#xff0c;用户可…

poi-tl 生成 word 文件(插入文字、图片、表格、图表)

文章说明 本篇文章主要通过代码案例的方式&#xff0c;展示 poi-tl 生成 docx 文件的一些常用操作&#xff0c;主要涵盖以下内容 &#xff1a; 插入文本字符&#xff08;含样式、超链接&#xff09;插入图片插入表格引入标签&#xff08;通过可选文字的方式&#xff0c;这种方…

昇思MindSpore学习笔记3--张量 Tensor

一、张量Tensor概念 矢量、标量和其他张量的计算函数&#xff0c;有内积、外积、线性映射以及笛卡儿积等 张量坐标在 n 维空间内&#xff0c;有 nr 个分量 每个分量都是坐标的函数,变换时每个坐标分量都按规则作线性变换 张量是一种特殊的数据结构&#xff0c;类似于数组和…

haproxy实现代理和负载均衡

HaProxy介绍&#xff1a; haproxy是法国开发者威利塔罗在2000年使用C语言开发的一个开源软件&#xff0c;是一款具备高并发(一万以上)、高性能的TCP和HTTP负载均衡器&#xff0c;支持基于cookie的持久性&#xff0c;自动故障切换&#xff0c;支持正则表达式及web状态统计&…

狼人杀系列

目录 杀人游戏&#xff08;天黑请闭眼&#xff09; &#xff08;1&#xff09;入门版 &#xff08;2&#xff09;标准版 &#xff08;3&#xff09;延伸版——百度百科 &#xff08;3.1&#xff09;引入医生和秘密警察 &#xff08;3.2&#xff09;引入狙击手、森林老人和…

学习gateway网关路由时遇到的问题

遇到这个问题先别慌&#xff0c;我们首先要检查是哪里出问题了&#xff0c;从报错信息中我们可以看到&#xff0c;他说 Unable to find GatewayFilterFactory with name -AddRequestHeader 找不到这个路由过滤器&#xff0c;所以导致网关设置失败&#xff0c;从这条信息上我…

Mac可以读取NTFS吗 Mac NTFS软件哪个好 mac ntfs读写工具免费

在跨操作系统环境下使用外部存储设备时&#xff0c;特别是当Windows系统的U盘被连接到Mac电脑时&#xff0c;常常会遇到文件系统兼容性的问题。由于Mac OS原生并不完全支持对NTFS格式磁盘的读写操作&#xff0c;导致用户无法直接在Mac上向NTFS格式的U盘或硬盘写入数据。下面我们…

web学习笔记(六十九)vue2

目录 1. vue2创建脚手架项目 2.vue2如何关闭eslint 1. vue2创建脚手架项目 &#xff08;1&#xff09;在cmd窗口输入npm install -g vue/cli命令行&#xff0c;快速搭建脚手架。 &#xff08;2&#xff09; 创建vue2项目 &#xff08;3&#xff09; 选择配置项目&#xff0c…

ic基础|功耗篇04:门级低功耗技术

大家好&#xff0c;我是数字小熊饼干&#xff0c;一个练习时长两年半的IC打工人。我在两年前通过自学跨行社招加入了IC行业。现在我打算将这两年的工作经验和当初面试时最常问的一些问题进行总结&#xff0c;并通过汇总成文章的形式进行输出&#xff0c;相信无论你是在职的还是…

pdf合并,pdf合并成一个pdf,pdf合并在线网页版

在处理pdf文件的过程中&#xff0c;有时我们需要将多个pdf文件合并成一个pdf文件。作为一名有着丰富计算机应用经验的技术博主&#xff0c;我将为您详细介绍如何将多个pdf文件合并成一个pdf文件。 pdf合并方法&#xff1a;使用&#xff0c; “轻云处理pdf官网” 打开 “轻云处…