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

【归并排序】| 详解归并排序 力扣912

🎗️ 主页:小夜时雨
🎗️专栏:归并排序
🎗️如何活着,是我找寻的方向

优雅

目录

  • 1. 题目解析
  • 2. 代码

1. 题目解析

题目链接: https://leetcode.cn/problems/sort-an-array/

在这里插入图片描述

我们上道题讲过归并排序的核心代码,建议先看一下这道题:合并两个有序数组 https://leetcode.cn/problems/merge-sorted-array/description/

归并排序的核心代码区间就是合并两个有序数组, 所以还是十分重要的, 接下来我们再来分析一下合并这个过程:

  • 首先这两个是非递减的整数数组,那么很自然的一个想法就是从头开始遍历两个数组,谁小取出来排队即可。
  • 取出来排队这个操作我们巨化为创建一个辅助数组,将数组中二者比较小的放入到这个辅助数组中, 直到遍历结束。
  • 最后再将辅助数组拷贝到原始数组中即可。整体的思路还是比较符合实际我们进行比较排序的情况的。

接下来我们来说一下归并排序的实现过程

归并排序具体实现过程:

  1. 首先我们先确定一个 key,把数组分为左右两个区间进行排序,此处通常都是选为中间区域,key = (left + right)/ 2 。
  2. 左右区间在进行排序,怎么排序:同样是在左区间找一个key,使得左区间又分为左右两个区间,同理右区间也是。我们发现都是先进行划分区间,一直划分。
  3. 划分直到左右区间内只有一个元素或者区间不存在,假设只有一个元素,那么不用排序天然就是有序的,此时要做的就是归并排序的核心操作:把左右区间的两个元素继续有序的合并,合并成一个有序的区间向上返回。
  4. 也就是说我们一直划分到划分不了区间为止,然后开始合并变成有序向上返回,越往上返回此时的数组也就是越有序的,直到最后的两个左右有序区间进行合并,那么最后这个区间就是有序的了,也就是排好序了。

看下面的分析图可能会更容易理解:

在这里插入图片描述

  • 也就是说我们想先排整体有序,以左区间为例:得先让左区间进行有序,让左区间有序就得让左区间的左右区间进行有序,然后合并,
  • 就这样一直划分下去,直到划分不了区间。我们发现这个过程其实有点像是二叉树的后序遍历,左右区间有序之后(类比先遍历左右子树),合并之后整体才会有序(遍历根节点)。
  • 接下来,后面会写到快排,快排则是相反的一个过程,类似于二叉树的前序遍历,后面很快会写到。

2. 代码

看下面的代码对照着上面的流程解析可能会更加的清楚。

   int[] tmp;  // 用一个全局的辅助数组public int[] sortArray(int[] nums) {int n = nums.length;tmp = new int[n];mergeSort(0, n - 1, nums);return nums;}private void mergeSort(int left, int right, int[] nums) {// 区间内只有一个元素或者元素不存在, 那么直接返回没有排序的必要if(left >= right) return;// 归并排序的主逻辑过程// 1. 找到一个中间位置int mid = (left + right) / 2;// [left, mid] [mid + 1, right] 划分为两个区间// 2. 先进行左右两边的分割,排个序。相信这两个函数能完成左右区间的排序// (递归不用太关注于具体的展开过程)mergeSort(left, mid, nums);mergeSort(mid + 1, right, nums);// 3. 两边排好序之后, 合并有序数组。(核心操作)// cur1 遍历 [left, mid] 这个区间// cur2 遍历 [mid + 1, right] 这个区间// i 遍历 tmp 辅助数组int cur1 = left, cur2 = mid + 1, i = 0;// while(cur1 <= left && cur2 <= right) {while(cur1 <= mid && cur2 <= right) {tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];}// 4.处理cur1 或者 cur2 还没有遍历完的数组while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];// 5. 把辅助数组中的数组拷贝到原数组中// j 遍历的是原数组, nums中的 【left, right】 这个区间for (int j = left; j <= right; j++) {// tmp 要从 0 开始遍历nums[j] = tmp[j - left];}} 

用到了一个全局的辅助数组,而不是每次进入递归都要重新new一下,这样写起来会方便一点。

🎗️🎗️🎗️ 好啦,到这里有关本题的分享就没了,如果感觉做的还不错的话可以点个赞,关注一下,你的支持就是我继续下去的动力,我们下期再见,拜了个拜~ ☆*: .。. o(≧▽≦)o .。.:*☆

相关文章:

  • python调用chatgpt
  • 使用npm发布自己的插件包
  • C#.Net筑基-类型系统②常见类型
  • Python中的TXT文档处理:导出与读取
  • Ubuntu22.04之去除文件结尾的^M符号(二百五十三)
  • 使用Kube-Bench对Kubernetes进行安全检测
  • 使用Selenium进行Web自动化:详细操作指南
  • 【PyQt5】python可视化开发:PyQt5介绍,开发环境搭建快速入门
  • YOLOv8中文分类标签显示问题解决
  • Windows桌面运维----第四天
  • 基于Java的高校校园点餐系统
  • c中编程题最有效率的方法算出2乘以8等於几
  • SpringBootWeb 篇-入门了解 Spring Cache 、Spring Task 与 WebSocket 框架
  • FPGA早鸟课程第二弹 | Vivado 设计静态时序分析和实际约束
  • SSL证书怎样配置部署更安全?
  • ----------
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • CEF与代理
  • github从入门到放弃(1)
  • Java新版本的开发已正式进入轨道,版本号18.3
  • Laravel 菜鸟晋级之路
  • nodejs实现webservice问题总结
  • React中的“虫洞”——Context
  • REST架构的思考
  • VUE es6技巧写法(持续更新中~~~)
  • 动态魔术使用DBMS_SQL
  • 码农张的Bug人生 - 见面之礼
  • 面试遇到的一些题
  • 七牛云假注销小指南
  • 如何编写一个可升级的智能合约
  • 思维导图—你不知道的JavaScript中卷
  • 微服务入门【系列视频课程】
  • 用Canvas画一棵二叉树
  • 终端用户监控:真实用户监控还是模拟监控?
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 大数据全解:定义、价值及挑战
  • ​水经微图Web1.5.0版即将上线
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #etcd#安装时出错
  • #QT(TCP网络编程-服务端)
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (8)STL算法之替换
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (ZT)一个美国文科博士的YardLife
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (力扣题库)跳跃游戏II(c++)
  • (三)Honghu Cloud云架构一定时调度平台
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET Core 成都线下面基会拉开序幕
  • .NET Core 项目指定SDK版本