java中mergesort函数怎么用,由mergeSort引发的一些思考

2023-10-29

重新梳理一下归并排序以及一些相关的东西。

对于归并排序大家如果需要回忆下是个什么东西的话,可以点击这个链接,里面有各种排序的动画演示以及讲解,比我再用文字赘述一遍要好得多,功能相当强大。

1460000020478631

先给出归并排序的js代码实现:

function mergeSort(arr, l, r) {

if (l === r) {

return;

}

let mid = Math.floor((r + l) / 2);

mergeSort(arr, l, mid);

mergeSort(arr, mid + 1, r);

merge(arr, l, mid, r);

}

function merge(arr, l, mid, r) {

let leftIndex = l;

let rightIndex = mid + 1;

let helpArr = [];

while(leftIndex <= mid && rightIndex <= r) {

let leftItem = arr[leftIndex];

let rightItem = arr[rightIndex];

if (leftItem < rightItem) {

helpArr.push(leftItem);

leftIndex++;

} else {

helpArr.push(rightItem);

rightIndex++;

}

}

// 这俩循环只会进去一个,因为经过上面的比较,要么左边部分走完了,要么右边部分走完了

while(leftIndex <= mid) {

helpArr.push(arr[leftIndex]);

leftIndex++;

}

while(rightIndex <= r) {

helpArr.push(arr[rightIndex]);

rightIndex++;

}

for (let index = 0; index < helpArr.length; index++) {

arr[l] = helpArr[index];

l++;

}

}

如何估计归并排序的时间复杂度呢?

由于上面采用了递归写法,我们使用master公式对递归进行时间复杂度估算,以下是公式详情。

T(n) = a*T(n/b) + O(n^d)

(1)、log(b, a) > d => 复杂度为O(n^log(b, a))

(2)、log(b, a) = d => 复杂度为O(n^d*logn)

(3)、log(b, a) < d => 复杂度为O(n^d)

a代表递归的次数,由于在mergeSort中调用了两次mergeSort,所以归并排序中a = 2。

b代表样本量被划分几份,由于我们对样本量是一分为二将数组分为left和right部分,所以归并排序中b = 2。

O(n^d)代表其他操作的时间复杂度,所以在归并排序中主要是merge这个函数,相当于是执行了一次数组遍历,则为O(n)。

a = 2,b = 2,d = 1根据master公式,复杂度为nlogn。

我们知道冒泡排序、选择排序、插入排序的时间复杂度都是O(n^2),当样本量比较大的时候,n^2比之nlogn差了可不是一星半点。这是为什么呢?因为在其他三种排序中,会浪费元素之间的比较,比如冒泡排序冒泡比较一轮只定位了一个元素,下一轮冒泡又只定位一个元素,会浪费元素之间的相互比较;而归并排序通过分治,由小到大进行比较合并的过程中,上一次比较合并的元素不会再次发生比较,有序的区域成规模增长,这样就不会浪费比较,节省了时间。

由归并排序引入数组小和问题和数组逆序对问题。

1460000020478632

根据小和的题目要求,我们思考一下可以发现,在归并排序过程中,left和right部分进行比较合并的时候,其实就可以找到左边部分比右边部分小的数,意思就是说我们可以很方便的在merge这个函数执行过程中来计算数组的小和且会快很多,因为合并的时候左右两遍都是有序的,如果一个数比右边的第一个数字小,我们可以得知这个数字肯定比右边全部的数字都小。

举个例子,比如left = [1,2,3],right = [4,5,6],1小于4,说明右边三个数都比1大,假如说小和等于sum,那么sum就要加1 * 3。

代码实现一下小和:

function smallSum(arr) {

if (!arr || arr.length < 2) {

return 0;

}

return mergeSort(arr, 0, arr.length - 1);

}

function mergeSort(arr, l, r) {

if (l === r) {

return 0;

}

let mid = Math.floor((l + r)/2);

return mergeSort(arr, l, mid)

+ mergeSort(arr, mid + 1, r)

+ merge(arr, l, mid, r)

}

function merge(arr, l, mid, r) {

let leftIndex = l;

let rightIndex = mid + 1;

let helpArr = [];

let sum = 0;

while(leftIndex <= mid && rightIndex <= r) {

let leftItem = arr[leftIndex];

let rightItem = arr[rightIndex];

if (leftItem < rightItem) {

/**相对于归并排序增加的部分**/

let tempSum = (r - rightIndex + 1) * leftItem

sum += tempSum;

/***************************/

helpArr.push(leftItem);

leftIndex++;

} else {

helpArr.push(rightItem);

rightIndex++;

}

}

/**这部分和归并排序merge函数一样**/

return sum;

}

对于小和都知道如何使用归并排序进行求解之后,逆序对其实和小和是一样的,只是反过来了而已,以下直接贴出代码。

function inversePairs(arr) {

if (!arr || arr.length < 2) {

return [];

}

return mergeSort(arr, 0, arr.length - 1);

}

function mergeSort(arr, l, r) {

if (l === r) {

return [];

}

let mid = Math.floor((l + r)/2);

return [

...mergeSort(arr, l, mid),

...mergeSort(arr, mid + 1, r),

...merge(arr, l, mid, r)

];

}

function merge(arr, l, mid, r) {

let leftIndex = l;

let rightIndex = mid + 1;

let helpArr = [];

let res = [];

while(leftIndex <= mid && rightIndex <= r) {

let leftItem = arr[leftIndex];

let rightItem = arr[rightIndex];

if (leftItem < rightItem) {

helpArr.push(leftItem);

leftIndex++;

} else {

/**相对于归并排序增加的部分**/

res.push([leftItem, rightItem]);

/***************************/

helpArr.push(rightItem);

rightIndex++;

}

}

/**这部分和归并排序merge函数一样**/

return res;

}

以上是对归并排序这部分内容进行的一些回顾和总结,希望能加深自己对它的理解,能在其他更多的地方将其运用上;如果有不正确的地方,大家可以踊跃指出,我将及时改正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java中mergesort函数怎么用,由mergeSort引发的一些思考 的相关文章

  • java 有序列表_Java 中的 List —— 有序序列

    List 在 java 中是个有序序列 一 容量 ArrayList 中有一个容量概念 表示基础数组的大小 无参时默认为 10 在需要的时候 比如 add操作 会自动增加其容量 LinkedList 没有这个概念 TreeMap 也有容量
  • SpringBoot忽略HTTPS请求的SSL证书

    报错如下 java security cert CertificateException No subject alternative names present 解决方案 1 创建SslUtil工具类 import java securi
  • FreeRTOS移植到STM32F103

    1 下载FreeRTOS源码 官网 FreeRTOS官网 下载第一个带有示例的 2 在基础工程文件中创建文件夹FreeRTOS 3 打开下载好的源码 将FreeRTOSv202212 01 FreeRTOS Source 里面的两个文件夹和
  • 软中断 简介

    前言 中断服务程序往往实在CPU关中断的条件下执行的 以避免中断嵌套而使控制复杂化 但是CPU关中断的时间不能太长 否则会丢失中断信号 因此Linux将中断服务程序分为 上半部 和 下半部 前者对时间要求比较严格 必须在中断请求发生后立即
  • linux底线模式,linux编辑命令vi

    vi vim 的使用 基本上 vi vim 共分为三种模式 分别是命令模式 Command mode 输入模式 Insert mode 和底线命令模式 Last line mode 命令模式 以vi打开一个文件就直接进入一般模式了 这是默认
  • Modbus CRC和LRC算法研究及代码实现

    一 CRC 循环冗余校验 1 CRC16实现流程 XOR 异或 N 字节的信息位 POLY CRC16 多项式计算 1010 0000 0000 0001 生成多项式 1 x2 x15 x16 在CRC16中 发送的第一个字节位低字节 2
  • VsCode 搭建 Java 开发环境

    前提 已经安装 jdk 一 vscode 安装插件 1 点击扩展 Ctrl Shift X 2 搜索查找 Java Extension Pack 3 点击安装 注意如果是 jdk 11 可以直接安装 如果是 jdk 8 那么需要先安装 La
  • CAD怎么查询面积

    第一步 打开cad图形 在菜单栏 点击 工具 第二步 调出工具选项 用鼠标指着 查询Q 激活查询命令 第三步 弹出查询的更多功能选项 点击 面积 第四步 这时候使用鼠标拾取需要查询的围成面积的各个关键点 第五步 拾取各个点 围成一个 封闭图
  • Python实验--手写五折交叉验证+调库实现SVM/RFC/KNN手写数字识别

    1 数据读取 先说一下要用到的数据集 数据集自取地址 链接 https pan baidu com s 1Vd2ADHEalSNnuOEcPJD8gQ 提取码 3hk6 数据集构成 0 9十个数字 总共1934个样本 以数字 n命名 每个样
  • LeetCode 1801. 积压订单中的订单总数(C++)

    思路 该题主要是对比销售 采购的价格来进行数组 队列的pop和push操作来实现 采用优先队列来实现排序 其中销售和采购对应小队列和大队列 对于 销售 操作 如果采购的积压订单中有出价格比自己的销售价格高 就出 对于 采购 操作 如果销售的
  • C++中虚析构函数的作用

    我们知道 用C 开发的时候 用来做基类的类的析构函数一般都是虚函数 可是 为什么要这样做呢 下面用一个小例子来说明 有下面的两个类 class ClxBase public ClxBase virtual ClxBase virtual v
  • 炫彩烟雾火焰人头

    文章目录 一 效果图以及素材 二 制作步骤 一 效果图以及素材 效果图 素材 烟雾画笔获取地址 二 制作步骤 打开素材 打开素材用魔棒工具选择图片背景 反选 ctrl i 选中人物肖像 复制新的一层 ctrl j 点击背景层 填充黑色 回到
  • 虚拟机作用

    1 调试软件 你物理机是64位系统 OD过不了SE壳的检测 那么只能安装个32位来进行调试了 2 测试兼容性 你是辅助或者软件的作者 想测试一下自己的软件是否兼容各个系统 VM是你最好的选择 3 安全性 玩黑客软件 远控抓J 03系统下载走
  • 没有用过这些插件,别说你在用vscode!

    点击上方 前端小苑 选择 置顶公众号 精品技术文章 热门资讯第一时间送达 小黑 怎么了 小粉 愁眉苦脸的 小粉 刚刚一个问题找了半个小时 居然 小黑 居然怎么样 小粉 说了你不许笑我蠢 找了半个小时 居然因为少写了一个括号 小黑 哈哈哈 小
  • 如何在linux命令行(终端)执行ipynb 文件。可以不依赖jupyter。

    安装 runipy pip install runipy 终端执行ipynb runipy
  • Latent Dirichlet Allocation(LDA)主题模型算法实现及源码解析

    Latent Dirichlet Allocation LDA 主题模型算法实现及源码解析 变量说明 整个程序步骤如下图 代码解析 1 读入文档 首先要读入语料库中的文档 每个文件行 开头是一个数字 代表有多少单词 接着是id count的
  • OpenCV——图像按位运算

    一 算法概述 1 逻辑运算 OpenCV4 针对两个图像之间的 与 或 异或 以及 非 运算分别提供了bitwise and bitwise or bitwise xor bitwise not 函数 图像像素间的逻辑运算与数字间的逻辑运算
  • linux禁用ssh弱加密算法,ssh弱加密算法漏洞修复

    8种机械键盘轴体对比 本人程序员 要买一个写代码的键盘 请问红轴和茶轴怎么选 ssh弱加密算法漏洞修复 SSH弱加密算法漏洞修复 1 A security scan turned up two SSH vulnerabilities 1 S
  • ES工作原理

    文章目录 一 架构设计 二 工作流程 1 ES写数据过程 2 ES搜索数据过程 3 ES读数据过程 三 写数据底层原理 四 倒排索引 五 ES为什么查询效率很高 1 倒排索引 2 单词词典 3 单词索引 4 位图BitMap 一 架构设计

随机推荐

  • vector的使用及模拟实现

    目录 一 vector的介绍及使用 1 vector的介绍 2 vector的使用 1 vector的定义 2 vector iterator的使用 3 vector 空间增长问题 4 vector 增删查改 3 vector 迭代器失效问
  • C++57个入门知识点_34_虚函数的模拟实现-理解(利用函数指针替代virtual的虚函数功能;虚函数的本质即为函数的覆盖,子类一旦对父类同名成员函数重载,对象在调用时使用的是子类的函数)

    上篇C 57个入门知识点 33 深入理解虚函数的原理 重点 间接调用 先查虚表地址 再查虚表中的虚函数指针 编译器先取对象的前4个字节地址 再取对应地址下函数指针 查看内存 反汇编的方法 成员函数指针 介绍了虚函数的原理 本篇将会介绍虚函数
  • 基于TMMI团队建设路线

    TMMI类似于CMMI成长路线 今天总结一下个人的思路 团队质量目标 1 质量之于产品 犹如生命之于人 公司的品牌价值直接通过产品质量体现 所以说质量对一个公司是何等重要 针对公司领导对产品质量的定位 确定质量方针与质量目标 再根据质量目标
  • JVM总结之类加载

    目录 JVM 运行时区域 方法区 klass模型 Oop模型 类加载过程 JVM调优总结 JVM 运行时区域 方法区 当JVM的类装载器加载 class文件 并进行解析 把解析的类型信息放入方法区 运行时的常量池是方法区的一部分 堆 虚拟机
  • ubuntu下eclipse无法编译 /bin/sh: 1: g++ not found 解决办法

    linux下code blocks无法编译运行提示 bin sh 1 g not found 的解决办法 今天在ubuntu 12 04 软件中心中选装了codeblocks 安装完成后却连最简单的hello world 都无法编译运行 编
  • hadoop集群搭建(基于docker-compose)

    1 创建工作目录 比如 home hadoop 需要配置2个文件 data是挂载目录 会自动创建 2 hadoop env 内容不用改 基本是默认配置 后续修改配置在这修改就行了 配置详情自己百度下 CORE CONF fs default
  • 【毕设】基于CycleGAN的风格迁移【三】代码迁移到服务器(Linux)及环境搭建

    1 假设服务器上已经安装好anaconda 2 通过u盘把代码文件 文件名pytorch CycleGAN and pix2pix master 拷到Desktop 桌面 上 3 打开Terminal 会直接进入anaconda终端 Lin
  • 程序员ChatGPT提示模板

    作为一个程序员 您总是在寻找优化您的工作流程 提高您的技能以及获得关于复杂编程概念的专家指导的方法 这就是 ChatGPT 的用武之地 一种基于人工智能的语言模型 可以利用其丰富的数据库知识帮助您完成编程任务 使用 ChatGPT 您可以提
  • 逆水寒服务器维护多长时间,逆水寒11月8日更新维护 更新时间内容介绍

    逆水寒11月8日周四例行更新 下面给大家带来具体的更新时间和更新内容汇总 有需要的一起来看看吧 各位自在同门 深秋金岁 霞光剑影 江湖秋色已深 不知各位同门在行走江湖之际 是否会停下脚步看一看金明池的红叶 逆水寒的江湖中万般风景 切莫不可辜
  • C++和C#程序语言的区别

    一直学习C 和C 两者之间的区别总结一下 目录 一 两种语言概述 C 语言 C 语言 二 两种语言对比 2 1运行依赖
  • android addview后view不能更新数据_热搜View效果

    接下来将一步一步实现如下 热搜词 效果 效果图 思路 通过观察效果图可以看出这个热搜词效果自定义View它是一个接一个的摆放的 而且每当一行的热搜词总宽度大于控件宽度的时候就会另起一行 因此我们可以考虑使用一个大的自定义的LinearLay
  • Spring 依赖注入

    依赖注入方式 1 构造器注入 2 setter注入 3 接口注入 maven pom xml配置 引入jar包和依赖jar
  • matlab读取文件夹的数据,根据文件名进行分类,加个分类后写入到不同文件夹中(.txt)

    读取文件夹下的所有文件 根据文件名中包含的内容进行分类 将不同的分类写入到不同的文件夹下 1 直接读取文件 根据文件名分类 不做任何处理 使用copyfile 将数据按照不同泳姿分类 不作其他处理 function Classificati
  • Linux IO实时监控iostat命令

    简介 iostat主要用于监控系统设备的IO负载情况 iostat首次运行时显示自系统启动开始的各项统计信息 之后运行iostat将显示自上次运行该命令以后的统计信息 用户可以通过指定统计的次数和时间来获得所需的统计信息 语法 iostat
  • nginx搭建前后端分离架构

    本人用的是vue cli 自动构建vue webpack 项目 这里不对webpack nginx进行讲解 本文主要解决前端开发环境搭建 测试环境搭建 生产环境搭建以及接口调试 一 需要工具 1 nginx 配置代理 2 webpack d
  • 了解基于Token的身份验证的来龙去脉

    简介 在Web领域基于Token的身份验证随处可见 在大多数使用Web API的互联网公司中 tokens 是多用户下处理认证的最佳方式 以下几点特性会让你在程序中使用基于Token的身份验证 1 无状态 可扩展 2 支持移动设备 3 跨程
  • C++的数据类型——常量

    2 2 常量 2 2 2 数值常量 数值常量就是通常所说的常数 在C 中可以从字面形式区分数值类型 1 整形常量 整数 的类型 通常有 int short int long int unsigned int 通常整数的类型不同 它们值的范围
  • Log4net创建日志及简单扩展

    1 概述 log4net是 Net下一个非常优秀的开源日志记录组件 log4net记录日志的功能非常强大 它可以将日志分不同的等级 以不同的格式 输出到不同的媒介 本文主要是介绍如何在Visual Studio2008中使用log4net快
  • tomcat8.5启动控制台乱码解决

    环境 win10 系统 tomcat8 5版本 现象 本地启动控制台日志乱码 解决办法 conf目录下 logging properties 文件 java util logging ConsoleHandler encoding UTF
  • java中mergesort函数怎么用,由mergeSort引发的一些思考

    重新梳理一下归并排序以及一些相关的东西 对于归并排序大家如果需要回忆下是个什么东西的话 可以点击这个链接 里面有各种排序的动画演示以及讲解 比我再用文字赘述一遍要好得多 功能相当强大 先给出归并排序的js代码实现 function merg