分治算法(5)_归并排序_排序数组

news2024/11/25 21:48:57

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

分治算法(5)_归并排序_排序数组

收录于专栏【经典算法练习】
本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1. 归并排序简介

分治思想:

归并排序的步骤:

归并排序的时间与空间复杂度

归并排序的优缺点: 

2. 题目链接

3. 题目描述

4. 解法

算法思路:

代码展示:

结果分析:

5. 快速排序与归并排序的比较 

算法思想:

时间与空间复杂度:

稳定性: 

实际应用:


1. 归并排序简介

分治思想:

分(Divide):将待排序数组分成两半,递归地对每一半进行归并排序。
治(Conquer):当子数组的大小为1时,数组自然是有序的。
合(Combine):将两个已排序的子数组合并成一个排序好的数组。 

归并排序的步骤:

分割:将数组不断分割,直到每个子数组只包含一个元素。
合并:将相邻的两个子数组合并成一个排序后的数组。合并的过程需要一个辅助数组来存放合并结果。 

归并排序的时间与空间复杂度

时间复杂度
最佳情况:O(n log n)
平均情况:O(n log n)
最坏情况:O(n log n)
归并排序的时间复杂度在所有情况下都是 O(n log n),因为它的合并过程总是需要遍历所有元素,而分割的深度是 log n。

空间复杂度
空间复杂度:O(n)
归并排序需要额外的空间来存储合并后的数组,因此其空间复杂度是 O(n)。

归并排序的优缺点: 

优点
稳定性:归并排序是一种稳定的排序算法,即相同元素的相对位置不会改变。
适用性广:对于大规模数据集或链表等数据结构,归并排序表现良好。
并行性:归并排序容易实现并行化,适合在多处理器环境中运行。
缺点
额外空间开销:需要 O(n) 的额外空间来存储合并结果,不适合内存有限的环境。
比较复杂:相比其他简单排序算法(如插入排序),实现起来相对复杂。 

2. 题目链接

OJ链接 : 排序数组 

3. 题目描述

给你一个整数数组 nums,请你将该数组升序排列。

你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

提示:

  • 1 <= nums.length <= 5 * 104
  • -5 * 104 <= nums[i] <= 5 * 104

4. 解法

算法思路:

归并排序的流程充分体现了[分而治之]的思想,大体过程为两步:

1. 分 : 将数组一分为二,一直分解到数组的长度为1,使整个数组的排序过程被分为[左半部排序] + [右半部排序];

2. 治 : 将两个较短额[有序数组组合成一个长的有序数组], 一直合并到最初的长度. 

代码展示:

class Solution {
    vector<int> tmp;
public:
    vector<int> sortArray(vector<int>& nums) {
        tmp.resize(nums.size());
        mergeSort(nums, 0, nums.size() - 1);
        return nums;
    }

    void mergeSort(vector<int>& nums, int left, int right)
    {
        if(left >= right) return;
        //选择中间点划分区间
        int mid = (left + right) >> 1;
        
        //[left, mid] [mid + 1, right]

        //2. 把左右区间排序
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);

        //3. 合并两个有序数组
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];
        //处理没有遍历完的数组
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];

        //还原
        for(int i = left; i <= right; i++)
            nums[i] = tmp[i - left];
    }
};

结果分析:

 示例分析:

5. 快速排序与归并排序的比较 

算法思想:

快速排序:
采用分治法(Divide and Conquer)策略。
选择一个“基准”元素,将待排序数组分成两部分:左侧为小于基准的元素,右侧为大于基准的元素。然后对左右两部分分别递归地进行快速排序。
归并排序:
同样采用分治法策略。
将待排序数组递归地分成两半,直到每个子数组只包含一个元素,然后再将两个已排序的子数组合并成一个有序数组。 

快速排序类似于二叉树的前序遍历(根左右)--确定好根然后递归遍历左右子树

归并排序类似于二叉树的后序遍历(左右根)--确定好左右子树在确定根 

时间与空间复杂度:

时间复杂度: 

快速排序:
最佳情况:O(n log n)(当基准元素均匀分布时)
平均情况:O(n log n)
最坏情况:O(n²)(当数组已经是有序的,且每次选择的基准都是最大或最小的元素)

归并排序:
最佳情况:O(n log n)
平均情况:O(n log n)
最坏情况:O(n log n)

空间复杂度: 

快速排序:
空间复杂度为 O(log n),主要是递归调用栈的空间消耗。实际上是一个原地排序算法,不需要额外的存储空间。
归并排序:
空间复杂度为 O(n),需要额外的数组来存储合并后的结果。 

稳定性: 

快速排序:
不稳定。在排序过程中,可能会改变相同元素的相对位置。

归并排序:
稳定。在合并的过程中,保持相同元素的相对位置不变。

实际应用:

快速排序:
通常在实际应用中比归并排序更快,特别是对于小规模数据和随机分布的数据。
适合在内存中排序,通常是许多标准库的默认排序算法(如C++的std::sort)。

归并排序:
适合处理大规模数据,尤其是链表等数据结构,因为它可以在合并的过程中避免内存的重新分配。
在外部排序(如排序大文件)中表现良好,因为可以高效地处理数据流。

 

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

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

相关文章

JavaSE——面向对象11:内部类(局部内部类、匿名内部类、成员内部类、静态内部类)

目录 一、内部类基本介绍 (一)内部类定义 (二)内部类基本语法 (三)内部类代码示例 (四)内部类的分类 二、局部内部类 三、匿名内部类(重要) (一)基本介绍 (二)基于接口的匿名内部类 (三)基于类的匿名内部类 (四)注意事项与使用细节 (五)匿名内部类的最佳实践——当…

leetcode-42. 接雨水 单调栈

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表…

Chrome浏览器调用ActiveX控件--allWebOffice控件

背景 allWebOffice控件能够实现在浏览器窗口中在线操作文档的应用&#xff08;阅读、编辑、保存等&#xff09;&#xff0c;支持编辑文档时保留修改痕迹&#xff0c;支持书签位置内容动态填充&#xff0c;支持公文套红&#xff0c;支持文档保护控制等诸多办公功能&#xff0c;本…

vim编辑器安装,并修改配置使其默认显示行数

centOS默认是未安装vim编辑器的&#xff0c;而vim编辑器相比vi编辑器更易用一些&#xff0c;如需使用vim编辑器&#xff0c;需要进行安装。 1.需要先配置本地yum源&#xff0c;参见如下链接&#xff1a; 点击查看如何配置本地yum源 2.安装vim编辑器&#xff0c;并修改配置。…

滑动窗口_找出字符串中所有字母异位词、串联所有单词的子串_C++

滑动窗口_找出字符串中所有字母异位词、串联所有单词的子串_C 1. 题目解析2. 算法分析3. 代码实现4. 举一反三&#xff1a;串联所有单词的子串 1. 题目解析 leetcode链接&#xff1a;https://leetcode.cn/problems/VabMRr/ 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p …

helm 测试安装redis

helm search repo redis # 搜索redis的chart helm show readme bitnami/redis # 展示安装相关文档&#xff08;readme文件&#xff09; 拉取指定版本的安装包&#xff08;chart&#xff09; helm pull bitnami/redis --version 17.4.3 解压安装包 tar -xf redis-17.4.3.tgz …

Vue3 动态路由实现的一种方法

动态路由 目的&#xff1a; 根据服务器传回来的数据动态的注册路由信息&#xff0c;登录用户的角色不同生成的菜单不同 使用插件做动态路由的好处&#xff1a; 路由页面增加或者减少时&#xff0c;只需要增加或减少相关的路由文件&#xff0c;不需要再修改代码 服务器返回的信…

POI数据的处理与分析

POI概念 POI&#xff08;Point of Interest&#xff0c;兴趣点&#xff09;数据指的是地理空间数据中的一类&#xff0c;表示某一具体地点或位置的信息。通常&#xff0c;这些数据包含位置坐标&#xff08;经纬度&#xff09;、名称、地址、类别和其他相关信息。POI 数据广泛应…

毕业设计 深度学习水果识别

文章目录 1 前言2 开发简介3 识别原理3.1 传统图像识别原理3.2 深度学习水果识别 4 数据集5 部分关键代码5.1 处理训练集的数据结构5.2 模型网络结构5.3 训练模型 6 识别效果 1 前言 Hi&#xff0c;大家好&#xff0c;这里是丹成学长&#xff0c;今天做一个 基于深度学习的水果…

算法剖析:双指针

文章目录 双指针算法一、 移动零1. 题目2. 算法思想3. 代码实现 二、 复写零1. 题目2. 算法思想3. 代码实现 三、 快乐数1. 题目2. 算法思想3. 代码实现 四、 盛水最多的容器1. 题目2. 算法思想3. 代码实现 五、有效三角形的个数1. 题目2. 算法思想3. 代码实现 六、 和为 s 的两…

【EXCEL数据处理】000020 案例 保姆级教程,附多个操作案例。EXCEL使用表格。

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【EXCEL数据处理】000020 案例 保姆级教程&#xff0c;附多个操作案例。…

【强训笔记】day27

NO.1 代码实现&#xff1a; #include<iostream>using namespace std;int n,m; int main() {cin>>n>>m;long long retn;for(int i0;i<m-1;i)retret*(n-1)%109;cout<<ret<<endl;return 0; }NO.2 思路&#xff1a;bfs遍历实现&#xff0c;dis…

Android架构--MVVM

一、开发架构 是什么&#xff1f; 二、Android开发中的架构 具体到Android开发中&#xff0c;开发架构就是描述 视图层、逻辑层、数据层 三者之间的关系和实施&#xff1a; 视图层&#xff1a;用户界面&#xff0c;即界面的展示、以及交互事件的响应。 逻辑层&#xff1a;为…

IL2CPP和Mono的区别

Mono 是一种开源的跨平台 .NET 框架实现&#xff0c;能够执行 C# 代码。Unity 使用 Mono 来处理 C# 脚本&#xff0c;并通过 JIT&#xff08;Just-In-Time&#xff09;即时编译器将托管代码转换为本地机器代码&#xff0c;随后在目标平台上执行 IL2CPP 代表 Intermediate Lang…

《业务三板斧:定目标、抓过程、拿结果》读书笔记3

关于目标&#xff0c;关键是共识目标&#xff1a; 为什么不是共识目标&#xff0c;而是共信目标&#xff1f; 共识目标是指管理者通过沟通&#xff0c;让所有团队成员就目标以及实现目 标的方法达成一致。当个人与组织、个人与个人之间出现“路径选择 差异”的时候&#xff0c;…

算法专题四: 前缀和

目录 1. 前缀和2. 二维前缀和3. 寻找数组的中心下标4. 除自身以外数组的乘积5. 和为k的子数组6. 和可被K整除的子数组7. 连续数组8. 矩阵区域和 博客主页:酷酷学!!! 感谢关注~ 1. 前缀和 算法思路: 根据题意, 创建一个前缀和数组, dp[i] dp[i -1] arr[i], 再使用前缀和数组,…

Go编译为可执行文件

在window下打包成其他系统可运行的文件 1.在window下打包成window下可执行文件 在项目main.go同级目录下&#xff0c;逐条执行以下命令 set CGO_ENABLED0 set GOOSwindows set GOARCHamd64 go build -o main-windows.exe main.go 2.在window下打包成linux 在项目main.go同级目…

Android Codec2 CCodec(十六)C2AllocatorGralloc

这一篇文章我们一起来瞧瞧2D&#xff08;Graphic&#xff09; buffer分配器C2AllocatorGralloc是如何工作的。 1、GraphicBuffer 在Android系统中&#xff0c;GraphicBufferAllocator和GraphicBufferMapper是与图形缓冲区&#xff08;Graphic Buffers&#xff09;管理相关的重…

Python爬取b站视频:验证cookie是否有效

具体代码 import requestsheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0,Referer: https://www.bilibili.com/,Origin: https://www.bilibili.com } def readCooki…

Nginx02-安装

零、文章目录 Nginx02-安装 1、Nginx官网 Nginx官网地址&#xff1a;http://nginx.org/ 2、Nginx下载 &#xff08;1&#xff09;Nginx下载 下载页地址&#xff1a;http://nginx.org/en/download.html &#xff08;2&#xff09;更老版本下载 下载页地址&#xff1a;http…