LeetCode 算法:排序链表 c++

news2024/11/29 12:32:42

原题链接🔗:排序链表
难度:中等⭐️⭐️

题目

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

示例 1
在这里插入图片描述

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

示例 2
在这里插入图片描述

输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]

示例 3

输入:head = []
输出:[]

提示

  • 链表中节点的数目在范围 [0, 5 * 104] 内
  • -105 <= Node.val <= 105

进阶:你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

题解

  1. 题解

LeetCode 上的 “Sort a linked list” 题目要求我们对链表进行排序。这个问题可以通过多种排序算法来解决,但是使用归并排序是最有效的方法,因为链表不适合使用快速排序或堆排序这类需要随机访问数据的算法。以下是使用归并排序对链表进行排序的解题思路:

  • 选择排序算法:由于链表的特性,归并排序是一个很好的选择。归并排序在链表上的实现相对简单,因为它不需要随机访问元素,只需要遍历链表。

  • 归并排序链表的步骤: 归并排序链表的步骤如下:

    • 分割链表:找到链表的中点,将链表分为两个子链表。
    • 递归排序:对两个子链表递归地进行排序。
    • 合并链表:合并两个已排序的子链表。
  • 实现分割链表:使用快慢指针法来找到链表的中点:

    • 初始化两个指针 slow 和 fast,都指向头节点。
    • fast 每次移动两步,slow 每次移动一步。
    • 当 fast到达链表末尾时,slow 将位于中点。
  • 实现递归排序 :递归地对分割后的两个子链表进行排序:

    • 如果子链表为空或只有一个节点,直接返回该子链表。
    • 否则,分割子链表并递归排序。
  • 实现合并链表:合并两个有序链表:

    • 创建一个哑节点(dummy node),用于简化边界条件的处理。
    • 使用一个指针 tail 指向哑节点,用于构建合并后的链表。
    • 比较两个链表头部的节点值,将较小的节点添加到合并后的链表中,并将对应的指针向前移动。
    • 重复上述步骤,直到两个链表中的一个为空。
    • 将非空链表的剩余部分直接连接到合并后的链表。
  1. 复杂度:时间复杂度O(nlogn),其中n是链表的长度;空间复杂度O(1)。
  2. c++ demo
#include <iostream>

// 定义链表节点
struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if (!head || !head->next) return head;

        // 找到链表的中点,准备分割链表
        ListNode* slow = head, * fast = head;
        while (fast->next && fast->next->next) {
            slow = slow->next;
            fast = fast->next->next;
        }

        // 切割链表
        ListNode* second = slow->next;
        slow->next = NULL;

        // 递归排序链表的两半
        ListNode* left = sortList(head);
        ListNode* right = sortList(second);

        // 合并排序后的链表
        return merge(left, right);
    }

private:
    ListNode* merge(ListNode* l1, ListNode* l2) {
        // 合并两个有序链表
        ListNode dummy(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;
    }
};

int main() {
    Solution solution;
    // 创建示例链表 4 -> 1 -> 3 -> 2 -> NULL
    ListNode* head = new ListNode(4);
    head->next = new ListNode(1);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(2);

    // 排序链表
    ListNode* sortedHead = solution.sortList(head);

    // 打印排序后的链表
    for (ListNode* node = sortedHead; node; node = node->next) {
        std::cout << node->val << " -> ";
    }
    std::cout << "NULL" << std::endl;

    // 释放链表内存
    while (sortedHead) {
        ListNode* temp = sortedHead;
        sortedHead = sortedHead->next;
        delete temp;
    }

    return 0;
}
  • 输出结果:

1 -> 2 -> 3 -> 4 -> NULL
在这里插入图片描述

归并排序

归并排序(Merge Sort)是一种分治算法,用于对数组或列表进行排序。它基于以下两个原则:

  • 分解(Divide):将数组分成两半,直到每个子数组只有一个元素。
  • 合并(Conquer):将有序的子数组合并成更大的有序数组。

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

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

相关文章

Windows11系统自动获取电脑IPV6地址,并且开机自动发送到指定邮箱

废话&#xff1a;最近放假回家&#xff0c;在家里突然想玩游戏了&#xff0c;Steamdeck性能终归有限。部分游戏始终玩的不爽&#xff0c;想到之前了解到的SunshnieMoonlight串流的方案&#xff0c;远程调用家里的电脑打游戏&#xff0c;简直不要太爽。 一顿折腾之后配置好了所有…

C语言| 数组的顺序查找

顺序查找 查找数组a中第一次出现数字m的下标&#xff0c;并输出该下标&#xff1b; 如果没有则输出sorry。 1 定义变量 数组a&#xff0c;n表示数组的个数&#xff0c; m要查找的数字 2 用sizeof()函数&#xff0c;求出数组元素的个数 3 从键盘中任意输出一个数字m&#xff0c;…

Docker网络介绍

网络是虚拟化技术中最复杂的部分&#xff0c;也是Docker应用中的一个重要环节。 Docker中的网络主要解决容器与容器、容器与外部网络、外部网络与容器之间的互相通信的问题。 这些复杂情况的存在要求Docker有一个强大的网络功能去保障其网络的稳健性。因此&#xff0c;Docker…

象战----第十二届中山市邀请赛正赛

本次的题解一定让大家享受脑细胞碰撞与再生死亡的感受&#xff01;定然酣畅淋漓&#xff01;请耐心的读完 简称&#xff1a;让脑袋死机。。。 象战 老规矩先分析在打码&#xff1a; 注意到题目告诉我们&#xff1a;四个角落是不能放的 那么 我们设象在(i,j).(注意&#xff1a…

120.网络游戏逆向分析与漏洞攻防-邮件系统数据分析-邮件发送功能的封装

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

遍历二叉树和线索二叉树

目录 一、*遍历二叉树 1.1遍历定义 1.2遍历目的 1.3遍历用途 1.4遍历方法 1.4.1先序遍历&#xff08;DLR&#xff09; 1.4.2中序遍历&#xff08;LDR&#xff09; 1.4.3后序遍历&#xff08;LRD&#xff09; 1.5根据遍历序列确定二叉树 1.6遍历算法的实现 1.6.1先序遍…

MySQL—索引—基础语法

目录 一、创建、查看以及删除索引的语法 &#xff08;1&#xff09;创建索引 1、1会用到一个关键字&#xff1a;CREATE。 1、2增加索引还可以用到另外一个关键字——ALTER TABLE 表名 ADD INDEX ... 。 2、解释。 &#xff08;2&#xff09;查看索引 1、查看索引需要用到…

PCL 三次样条插值(二维点)

一、简介 在插值计算中,最简单的分段多项式近似应该是分段线性插值,它由连接一组数据点组成,仅仅只需要将这些点一一用直线进行顺序相连即可。不过线性函数插值的缺点也很明显,就是在两个子区间变化的比较突兀,也就是没有可微性(不够光滑)。因此我们需要更为符合物理情况…

Day58 代码随想录打卡|二叉树篇---将有序数组转换为二叉搜索树

题目&#xff08;leecode T108&#xff09;&#xff1a; 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 方法&#xff1a;用有序数组构造平衡二叉搜索树&#xff0c;和我们之前有一题的思路差不多&#xff0c…

计算机毕设JAVA——学习考试管理系统(基于SpringBoot+Vue前后端分离的项目)

学习考试管理系统 概要系统架构技术运行环境系统功能项目演示图片 概要 网络上许多计算机毕设项目开发前端界面设计复杂、不美观&#xff0c;而且功能结构十分单一&#xff0c;存在很多雷同的项目&#xff1a;页面基本上就是套用固定模板&#xff0c;换个颜色、改个文字&#…

如何使用gprof对程序进行性能分析

如何使用gprof对程序进行性能分析 目录 1 gprof概述 2 gprof原理简述 3 gprof使用 3.1 gprof使用简述 3.2 gprof使用示例 4 小结 1 gprof概述 gprof 是 一个 GNU 的程序性能分析工具&#xff0c;可以用于分析C\C程序的执行性能。gprof工具可以统计出各个函数的调用次数、执…

C语言小例程

题目&#xff1a;两个乒乓球队进行比赛&#xff0c;各出三人。甲队为a,b,c三人&#xff0c;乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比&#xff0c;c说他不和x,z比&#xff0c;请编程序找出三队赛手的名单。 #include <stdio.h> #in…

【职场人】职场进化记:我的“不惹人厌邀功精”之路

刚步入职场的我&#xff0c;就像一张白纸&#xff0c;什么都不懂&#xff0c;只知道埋头苦干。但渐渐地&#xff0c;我发现那些经常“冒泡”的同事似乎总能得到更多的关注和机会。我不禁想&#xff1a;“我是否也要成为那样一个‘邀功精’呢&#xff1f;” 不过&#xff0c;我…

BFS:解决最短路问题

文章目录 什么是最短路问题&#xff1f;1.迷宫中离入口最近的出口2.最小基因变化3.单词接龙4.为高尔夫比赛砍树总结 什么是最短路问题&#xff1f; 最短路问题是图论中的经典问题&#xff0c;旨在寻找图中两个节点之间的最短路径。常见的最短路算法有多种&#xff0c;这次我们…

MSPM0G3507——GPIO例程讲解1——input_capture

函数&#xff1a; 参数&#xff1a; 返回值&#xff1a; 主函数代码&#xff1a; #include "ti_msp_dl_config.h"extern volatile uint32_t interruptVectors[];int main(void) {SYSCFG_DL_init(); //把所有的LED灯和按键初始化了一…

idea导入文件里面的子模块maven未识别处理解决办法

1、File → Project Structure → 点击“Modules” → 点击“” → “Import Model” 2、可以看到很多子模块&#xff0c;选择子模块下的 pom.xml 文件导入一个一个点累死了&#xff0c;父目录下也没有pom文件 解决办法&#xff1a;找到子模块中有一个pom.xml文件&#xff0c;…

【CT】LeetCode手撕—42. 接雨水

目录 题目1- 思路2- 实现⭐42. 接雨水——题解思路 3- ACM实现 题目 原题连接&#xff1a;42. 接雨水 1- 思路 模式识别&#xff1a;求雨水的面积 ——> 不仅是只求一个比当前元素大的元素&#xff0c;还要求面积 单调栈 应用场景&#xff0c;需要找到左边比当前元素大的…

钓鱼隐藏--文件后缀压缩文件捆绑文件

免责声明:本文仅做技术交流与学习... 目录 文件后缀-钓鱼伪装-RLO 压缩文件-自解压-释放执行 捆绑文件-打包加载-释放执行 文件后缀-钓鱼伪装-RLO 改后缀--伪装 w.exe wgpj.exe (要改的后缀反写)(jpg--->gpj) | (光标移到要改的后缀的前边)(w和g中间) …

Sequelize入门及简单的增删改查

前言 学习一下NodeJS怎么使用Sequelize怎么查询数据库数据 一、Sequelize是什么&#xff1f; Sequelize 是一个基于 promise 的 Node.js ORM, 二、搭建项目 1.安装过程 npm i -g sequelize-cli //全局安装sequelize-clinpm i sequelize mysql2 //安装sequelize和mysql2…

基于YOLOv5的交通标志检测的设计与实现

简介 在智能交通系统中,交通标志的准确检测与识别对提高道路安全和交通效率至关重要。为了实现这一目标,我们开发了一种基于YOLOv5目标检测模型的交通标志检测系统。本报告将详细介绍该系统的实际应用与实现,包括系统架构、功能实现、使用说明、检测示例、数据集获取与介绍…