【练习】分治--归并排序

  • 🎥 个人主页:Dikz12
  • 🔥个人专栏:算法(Java)
  • 📕格言:吾愚多不敏,而愿加学
  • 欢迎大家👍点赞✍评论⭐收藏

目录

归并排序

代码实现 

交易逆序对的总数 

题目描述 

​编辑 题解

代码实现

 计算右侧小于当前元素的个数

题目描述 

​编辑 题解

 代码实现

 翻转对

题目描述 

​编辑 题解

代码实现 


归并排序

归并排序( MERGE-SORT )是建立在归并操作上的一种有效的排序算法 ,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子 序列段间有序。若 将两个有序表合并成一个有序表 ,称为二路归并。 时间复杂度:O(N*logn)

⼤体过程分为两步:
  • 分:将数组⼀分为⼆为两部分,⼀直分解到数组的⻓度为 1 ,使整个数组的排序过程被分为 「左半部分排序」 + 「右半部分排序」;
  • 治:将两个较短的「有序数组合并成⼀个⻓的有序数组」,⼀直合并到最初的⻓度。

代码实现 

class Solution {int[] tmp;public int[] sortArray(int[] nums) {tmp = new int[nums.length];mergeSort(nums,0,nums.length-1);return nums;}public void mergeSort(int[] nums,int left,int right) {if(left >= right) {return;}//1.根据中间点拆分数据.左、右两部分int mid = (left + right) / 2;mergeSort(nums,left,mid);mergeSort(nums,mid+1,right);//2.合并两个有序数组// int[] tmp = new int[right - left + 1];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++];}// 3.还原到原数组for(int j = left; j <= right; j++) {nums[j] = tmp[j - left];}}
}

交易逆序对的总数 

题目描述 

 题解

因此,我们可以利⽤归并排序的过程,先求出左半数组中逆序对的数量,再求出右半数组中逆序对的 数量,最后求出⼀个选择左边,另⼀个选择右边情况下逆序对的数量,三者相加即可。 (利⽤数组的有序性,快速统计 出逆序对的数量,⽽不是将所有情况都枚举出来)
最核心的问题,如何在合并两个有序数组的过程中,统计出逆序对的数量?
  1. 找出该数之前,有多少个数比它大
  2. 找出该数之后,有多少个数比它小.

代码实现

    int[] tmp;public int reversePairs(int[] nums) {tmp = new int[nums.length];return mergerSort(nums,0,nums.length - 1);}public int mergerSort(int[] nums,int left,int right) {//1.递归出口if(left >= right) {return 0;}// 2.分成左右两部分int ret = 0;int mid = (left + right) >> 1;ret += mergerSort(nums,left,mid);ret += mergerSort(nums,mid + 1,right);//3.合并// int[] tmp = new int[right - left + 1];int cur1 = left, cur2 = mid + 1, i = 0;//数组下标while(cur1 <= mid && cur2 <= right) {if(nums[cur1] <= nums[cur2]) {tmp[i++] = nums[cur1++];}else {//计数ret += mid - cur1 + 1;tmp[i++] = nums[cur2++];}}while(cur1 <= mid) {tmp[i++] = nums[cur1++];}while(cur2 <= right) {tmp[i++] = nums[cur2++];}// 还原数组for(int j = left; j <= right; j++) {nums[j] = tmp[j - left];}return ret;}

 计算右侧小于当前元素的个数

题目描述 

 题解

解法:归并排序. 

 代码实现

    int[] ret; // 结果数组int[] index; // 存放原始数据的下标int[] tmpNums; // 辅助数组int[] tmpIndex;public List<Integer> countSmaller(int[] nums) {int n = nums.length;ret = new int[n];index = new int[n];tmpIndex = new int[n];tmpNums = new int[n];// 初始化原始数据的下标for (int i = 0; i < n; i++) {index[i] = i;}// 归并排序mergerSort(nums, 0, n - 1);//List<Integer> list = new ArrayList<>();for (int x : ret) {list.add(x);}return list;}public void mergerSort(int[] nums, int left, int right) {// 1.递归出口if (left >= right) {return ;}// 2.拆分成左右两部分int mid = (left + right) >> 1;mergerSort(nums, left, mid);mergerSort(nums, mid + 1, right);// 合并int cur1 = left, cur2 = mid + 1, i = 0;while (cur1 <= mid && cur2 <= right) {// 降序排 => 谁大动谁if (nums[cur1] <= nums[cur2]) {tmpNums[i] = nums[cur2];// 绑定移动tmpIndex[i++] = index[cur2++];} else {ret[index[cur1]] += right - cur2 + 1;tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}}while (cur1 <= mid) {tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while (cur2 <= right) {tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}for(int j = left; j <= right; j++) {nums[j] = tmpNums[j - left];index[j] = tmpIndex[j - left];}}

 翻转对

题目描述 

 题解

翻转对和逆序对的定义⼤同⼩异,逆序对是前⾯的数要⼤于后⾯的数。⽽翻转对是前⾯的⼀个数要 ⼤于 后⾯某个数的两倍 。因此,我们依旧可以⽤归并排序的思想来解决这个问题。
但是,归并排序,要求的是左边元素大于右边元素;而这道题的条件是,左边元素大于右边元素的两倍,所以, 我们需要在归并之前完成翻转对的统计。

代码实现 

    int[] tmp;public int reversePairs(int[] nums) {int n = nums.length;tmp = new int[n];return mergerSort(nums,0,n - 1);}public int mergerSort(int[] nums,int left,int right) {//1.递归结束条件if(left >= right) {return 0;}//2.拆分数组分为左右两部分int ret = 0;int mid = (left + right) >> 1;ret += mergerSort(nums,left,mid);ret += mergerSort(nums,mid + 1,right);//3.计算翻转对(降序)int cur1 = left,cur2 = mid + 1,i = 0;while(cur1 <= mid) {// while(cur2 <= right && nums[cur2] < nums[cur1] / 2.0 ) {//     ret += right - cur2 + 1;//     cur1++;// }// if(cur2 > right) {//     break;// }// cur2++;while(cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) {cur2++;}if(cur2 > right) {break;}ret += right - cur2 + 1;cur1++;}//4.合并两个有序数组cur1 = left;cur2 = mid + 1;while(cur1 <= mid && cur2 <= right) {if(nums[cur1] <= nums[cur2]) {tmp[i++] = nums[cur2++];}else{tmp[i++] = nums[cur1++];}}while(cur1 <= mid) {tmp[i++] = nums[cur1++];}while(cur2 <= right) {tmp[i++] = nums[cur2++];}for(int j = left; j <= right; j++) {nums[j] = tmp[j - left];}return ret;}

 

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

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

相关文章

JAVA从入门到精通之入门初阶(二)

1. 自动类型转换 自动类型转换&#xff1a;类型范围小的变量可以赋值给类型范围大的变量 byte->int public class java_7_10 {public static void main(String[] args) {//自动类型转换//类型范围小的变量可以赋值给类型范围大的变量 byte->intbyte a 12;int b a;//自动…

C语言 ——— 输入两个正整数,求出最小公倍数

目录 何为最小公倍数 题目要求 代码实现 方法一&#xff1a;暴力求解法&#xff08;不推荐&#xff09; 方法二&#xff1a;递乘试摸法&#xff08;推荐&#xff09; 何为最小公倍数 最小公倍数是指两个或者多个正整数&#xff08;除了0以外&#xff09;的最小的公共倍数…

【LeetCode】205. 同构字符串

认真地分类讨论&#xff0c;评判复杂度&#xff0c;再决定是否要写代码执行。整套流程干净利落&#xff0c;不存在主观臆想&#xff0c;也不会有对事实结果计算的巨大偏差。 1. 题目 2. 分析 这里提供一版可以解题的思路。 定义两个词典&#xff0c;这两个词典分别记录s字符串…

DHC2-2多时段电子式时间继电器 带底座 约瑟JOSEF

DHC2多时段电子式时间继电器 DHC2-H多时段电子式时间继电器 DHC2-1多时段电子式时间继电器 DHC2-2多时段电子式时间继电器 DHC2-3多时段电子式时间继电器 一、特点 超小型面板尺寸DIN 36X36mm(DHC1)、DIN 48X48m(DHC2) 有延时吸合、延时释放、等周期循环三种规格 可替代…

kibana连接elasticsearch(版本8.11.3)

前言 elasticsearch在8版本之后就出现了很大变化&#xff0c;由于kibana版本需要需elasticsearch进行版本对象&#xff0c;kibana连接方式也出现了很大变化。我在这里记录下自己的踩坑记录。 服务部署 本文中的服务都是在docker环境中部署的。其中elasticsearch版本和kibana版…

5G-A通感融合赋能低空经济-RedCap芯片在无人机中的应用

1. 引言 随着低空经济的迅速崛起&#xff0c;无人机在物流、巡检、农业等多个领域的应用日益广泛。低空飞行器的高效、安全通信成为制约低空经济发展的关键技术瓶颈。5G-A通感一体化技术通过整合通信与感知功能&#xff0c;为低空网络提供了强大的技术支持。本文探讨了5G-A通感…

OpenCV 寻找棋盘格角点及绘制

目录 一、概念 二、代码 2.1实现步骤 2.2完整代码 三、实现效果 一、概念 寻找棋盘格角点&#xff08;Checkerboard Corners&#xff09;是计算机视觉中相机标定&#xff08;Camera Calibration&#xff09;过程的重要步骤。 OpenCV 提供了函数 cv2.findChessboardCorners…

什么? CSS 将支持 if() 函数了?

CSS Working Group 简称 CSSWG, 在近期的会议中决定将 if() 添加到 CSS Values Module Level 5 中。 详情可见&#xff1a;css-meeting-bot 、[css-values] if() function 当我看到这个消息的时候&#xff0c;心中直呼这很逆天了&#xff0c;我们知道像 less 这些 css 这些预…

用Speedtest-Tracker跟踪上网速度(续)

什么是 Speedtest Tracker ? Speedtest Tracker 是一款自托管互联网性能跟踪应用程序&#xff0c;可针对 Ookla 的 Speedtest 服务运行速度测试检查。 之前老苏介绍的另一个 https://github.com/henrywhitaker3/Speedtest-Tracker 已被放弃。现在这个是积极维护的替代品&#…

STM32编写代码之嵌入式常用位操作

在单片机编程的过程中&#xff0c;经常会遇到位操作进行赋值&#xff0c;例如 //程序1 int a 0,b 0x5b,c 0; //1 for (i 0; i < 8; i ) { //2a b & (0x80 >> i)); //3 c | (0x80 >> i); //4 } 这些位操作是什么意思呢&#xff1f…

GuLi商城-商品服务-API-品牌管理-JSR303自定义校验注解

自定义注解规则: 可以参考@NotNull注解 package com.nanjing.common.valid;import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target;i…

跨域解决方案

跨域 当发起请求的协议号、域名、端口号中有一个不一样时就会导致跨域 跨域解决方案 分为两个方面&#xff0c;是否可以修改服务器端。 可以修改服务器端&#xff1a;cors方案、jsonp方案 不可以修改服务器端&#xff1a; 使用代理&#xff1a; 因为跨域主要是针对浏览器…

T113-i系统启动速度优化方案

背景: 硬件:T113-i + emmc 软件:uboot2018 + linux5.4 + QT应用 分支:longan 问题: 全志T113-i的官方系统软件编译出的固件,开机启动时间10多秒,启动时间太长,远远超过行业内linux系统的开机速度,需要进一步优化。 T113-i 优化后启动速度实测数据 启动阶段启动时间(…

Fastgpt本地使用Docker Compose 快速部署

使用 Docker Compose 快速部署 FastGPT 部署架构图 MongoDB:用于存储除了向量外的各类数据 PostgreSQL/Milvus:存储向量数据 OneAPI: 聚合各类 AI API,支持多模型调用 (任何模型问题,先自行通过 OneAPI 测试校验) 推荐配置 PgVector版本 体验测试首选 环境最低配置(单…

MySql性能调优04-[MySql事务与锁机制原理]

MySql事务与锁机制原理 从undo与redo日志&#xff0c;理解事务底层ACID底层原理事务四大隔离级别事务底层锁机制和MVCC并发优化机制串行化底层实现机制读已提交和可重复读底层实现MVCC机制详解脏写问题(重要)读已提交&#xff1f;实现机制 BufferPool缓存与redo日志是如何提升事…

海康相机GrabImage

#include <stdio.h> #include <Windows.h> #include <process.h> #include <conio.h> #include "MvCameraControl.h"bool g_bExit false;// ch:等待按键输入 | en:Wait for key press void WaitForKeyPress(void) {while(!_kbhit()){Sleep(…

6.S081的Lab学习——Lab11: Network

文章目录 前言Network提示&#xff1a;实现e1000_transmit的一些提示&#xff1a;实现e1000_recv的一些提示&#xff1a; 解析 总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招。打算尝试6.S081&#xff0c;将它的Lab逐一实现&#xff0c;并记录期间心酸历程。 代码下…

STM32MP135裸机编程:支持内存非对齐访问

0 前言 使用stm32官方可视化初始化代码生成工具STM32CubeMX生成的工程GCC编译选项默认不支持非对齐访问&#xff0c;在我们进行非对齐的访问时就会进入数据异常中断DAbt中。为了解决这一问题&#xff0c;我们需要在GCC编译选项中加上一处配置。 1 操作方法 右键STM32CubeIDE…

【Linux】:重定向和缓冲区

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家带来关于重定向和缓冲区的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精…

Paddle 打包部署

PaddleOCR 打包部署exe 心酸历程 PaddleOCR部署exe模式PaddleOCR安装到本地(稍后有时间再写)PaddleOCR打包过程异常问题记录&#xff01;&#xff01;&#xff01;&#xff01;No such file or directory: D:\\py_project\\paddleOCR\\dist\\paddleOCR\\_internal\\paddleocr\\…