【算法基础】(一)基础算法 --- 归并排序

news2025/3/1 14:23:29

✨个人主页:bit me
✨当前专栏:算法基础
🔥专栏简介:该专栏主要更新一些基础算法题,有参加蓝桥杯等算法题竞赛或者正在刷题的铁汁们可以关注一下🌹 🌹 🌹

归并排序

  • 💤一.归并排序(分治)
  • 💨二.逆序对的数量

 

💤一.归并排序(分治)

题目要求:

给定你一个长度为 n 的整数数列。
 
请你使用归并排序对这个数列按照从小到大进行排序。
 
并将排好序的数列按顺序输出。

输入格式:

输入共两行,第一行包含整数 n。
 
第二行包含 n 个整数(所有整数均在 1∼10^9 范围内),表示整个数列。

输出格式:

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围:

1≤n≤100000

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5

快排思路:

  1. 确定分界点:mid = (l + r) / 2
  2. 递归排序left,right
  3. 归并 —— 合二为一

导图:

在这里插入图片描述

  1. 首先我们需要设置下数据的范围,然后两个创建数组来方便我们后续使用,一个数组用来读取输入元素个数,一个数组用来临时归并合二为一
private static final int N = 100000 + 6;
private static int[] q = new int[N];
private static int[] t = new int[N];
  1. 数据的读取输入
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String str = input.readLine();
int n=Integer.parseInt(str);
String[] strs = input.readLine().split(" ");
for (int i = 0; i < n; i++) {
    q[i] = Integer.parseInt(strs[i]);
}

注意:在这里用BufferedReader是要比Scanner要好的,速度更快一点

  1. 然后排序函数代入,排序函数的实现
if (l >= r) return;
int mid = l + r >> 1;
sort(q, l, mid);
sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r) {
    if (q[i] <= q[j]) {
        t[k++] = q[i++];
    }
    else {
        t[k++] = q[j++];
    }
}
while (i <= mid) {
    t[k++] = q[i++];
}
while (j <= r) {
    t[k++] = q[j++];
}
for (i = l, j = 0; i <= r; i++, j++) {
    q[i] = t[j];
}
  1. 当左极值点大于等于右极值点,说明只有一个元素或者没有,直接返回
  2. 让分界点mid直接等于中点值
  3. 分界点mid俩边区域分别进行递归排序,数组名,起点和终点
  4. 两个指针i和j,分别从左边和中间开始往后走,分别比较元素大小,小的就纳入数组t中,直到有一个区域指针走完了,然后直接把另外的一个区域后面的衔接到数组t后面,就完成了排序
  5. 最后把t数组中的结果重新归并到数组q中

附上总的代码

public class TestDemo {
    private static final int N = 100000 + 6;
    private static int[] q = new int[N];
    private static int[] t = new int[N];

    public static void main(String[] args) throws IOException {
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        String str = input.readLine();
        int n=Integer.parseInt(str);
        String[] strs = input.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            q[i] = Integer.parseInt(strs[i]);
        }
        sort(q, 0, n - 1);
        for (int i = 0; i < n; i++){
            System.out.printf("%d ", q[i]);
        }
    }

    private static void sort(int[] q, int l, int r) {
        if (l >= r) return;
        int mid = l + r >> 1;
        sort(q, l, mid);
        sort(q, mid + 1, r);
        int k = 0, i = l, j = mid + 1;
        while (i <= mid && j <= r) {
            if (q[i] <= q[j]) {
                t[k++] = q[i++];
            }
            else {
                t[k++] = q[j++];
            }
        }
        while (i <= mid) {
            t[k++] = q[i++];
        }
        while (j <= r) {
            t[k++] = q[j++];
        }
        for (i = l, j = 0; i <= r; i++, j++) {
            q[i] = t[j];
        }
    }
}

 

💨二.逆序对的数量

题目要求:

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。
 
逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。

输入格式:

第一行包含整数 n,表示数列的长度。
 
第二行包含 n 个整数,表示整个数列。

输出格式:

输出一个整数,表示逆序对的个数。

数据范围:

1≤n≤100000,
数列中的元素的取值范围 [1,10^9]。

输入样例:

6
2 3 4 5 6 1

输出样例:

5

结合归并排序:

  1. [L,R] => [L,mid] + [mid+1,R]
  2. 递归排序[L,mid]和[mid+1,R]
  3. 归并,将左右两个有序序列合并成一个有序序列

导图:

在这里插入图片描述

我们可以继续分治:

整个区间的逆序数对分为左区间的逆序数对,右区间逆序数对和两个区间各组成的逆序数对,其中左区间和右区间的逆序对数量很直观,重点在于两者各取其一组成的逆序对怎么求

  1. 左区域逆序对数量:merge_sort(L,mid)
     
  2. 右区域逆序对数量:merge_sort(mid+1,R)
     
  3. 由归并排序我们可以知道左右俩区域都是按顺序来排列的,那么我们只需要找到左区域第一个大于右区域的最小数,那么它后面的数都是大于右区域的那个数字的,我们不妨设左区域那个元素下标为i,所以我们需要统计的个数是 mid - i + 1,恰巧在归并排序的合并过程中正好有两边序列依次比大小的过程
    if (a[i] <= a[j]) tem[k++] = a[i++]; else { tem[k++] = a[j++]; }
    else中的语句即代表左边数列中的数大于右边中的数了,我们可以在此时将mid-i+1加到总答案中去if (a[i] <= a[j]) tem[k++] = a[i++]; else { res += mid - i + 1; tem[k++] = a[j++]; }
     
  4. 问题解决后,我们的函数还没有解决问题的能力,只需要在递归出口的时候return 0;因为递归结束的时候数列中只有一个数了,不存在逆数对。还需要在递归归并排序的时候统计两边的逆序对数量之和long res = mergeSort(a, l, mid) + mergeSort(a, mid + 1, r);即可。

注意:题目中的数据范围最大是100000,一般对于数据范围大于10w的题目就要考虑数据溢出、时间复杂度等问题

当数列是一个倒序的数列时应该是逆序对数量最大的时候,每一个数可以和他后面所有的数形成逆数对,如果有n个数,那么总的逆序对数量为:(n-1)+(n-2)+……+1即n(n−1)/2个,大约n^2 / 2个,代入10w的数据范围得最多逆数对个数为:5×10 ^ 9,这个数据大于int的范围。所以这个题用int的话会溢出,我们采用long来存结果

附上总的代码

public class Main {
    public static void main(String[] args)  {
        Scanner scanner = new Scanner(new InputStreamReader(System.in));
        int n = scanner.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = scanner.nextInt();
        }
        System.out.println(merge_Sort(a, 0, n - 1));
        scanner.close();
    }

    private static long merge_Sort(int[] a, int l, int r) {
        if (l >= r){
            return 0;
		}
        int mid = l + r >> 1;
        long res = merge_Sort(a, l, mid) + merge_Sort(a, mid + 1, r);
        int tmp[] = new int[r-l+1];
        int k = 0, i = l, j = mid + 1;
        while (i <= mid && j <= r) {
            if (a[i] <= a[j]){
                tmp[k++] = a[i++];
            }else {
                res += mid - i + 1;
                tmp[k++] = a[j++];
            }
        }
        while (i <= mid){
            tmp[k++] = a[i++];
        }
        while (j <= r){
            tmp[k++] = a[j++];
        }
        for(i=l,j=0;i<=r;i++,j++){
        	a[i]=tmp[j];
        }
        return res;
    }
}

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

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

相关文章

猴子也能学会的jQuery第十期——jQuery元素操作(上)

&#x1f4da;系列文章—目录&#x1f525; 猴子也能学会的jQuery第一期——什么是jQuery 猴子也能学会的jQuery第二期——引用jQuery 猴子也能学会的jQuery第三期——使用jQuery 猴子也能学会的jQuery第四期——jQuery选择器大全 猴子也能学会的jQuery第五期——jQuery样式操作…

基于拟蒙特卡洛模拟法的随机潮流计算matlab程序

电力系统随机潮流计算中常采用模拟法&#xff0c;该方法原理简单、使用方便&#xff0c;能够精确地模拟实际物理过程&#xff0c;但是简单的蒙特卡洛模拟法收敛速度很慢&#xff0c;要得到精确的结果需要以大量的计算时间为代价。本章在此基础上提出了基于拟蒙特卡洛模拟的随机…

【菜菜的sklearn课堂笔记】逻辑回归与评分卡-用逻辑回归制作评分卡-异常值和样本不均衡处理

视频作者&#xff1a;菜菜TsaiTsai 链接&#xff1a;【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili 描述性统计处理异常值 现实数据永远都会有一些异常值&#xff0c;首先我们要去把他们捕捉出来&#xff0c;然后观察他们的性质。注意&#xff0c…

【雷达检测】基于复杂环境下的雷达目标检测技术附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

3.6、媒体接入控制

1、基本概念 有多台主机连接到这根同轴电缆上&#xff0c;共享这跟传输媒体&#xff0c;形成了总线型的局域网。 各主机竞争使用总线&#xff0c;随机的在信道发送数据。 主机 C 与主机 D 同时使用总线来发送数据&#xff0c;这必然会产生所发送信号的碰撞 2、静态划分信道…

二阶锥松弛在配电网最优潮流计算中的应用(IEEE33节点配电网最优潮流算例matlab程序)(yalmip+cplex)

二阶锥规划在配电网最优潮流计算中的应用IEEE33节点配电网最优潮流算例matlab程序&#xff08;yalmipcplex&#xff09; 参考文献&#xff1a;二阶锥规划在配电网最优潮流计算中的应用 最优潮流计算是电网规划、优化运行的重要基础。首先建立了配电网全天有功损耗最小化的最优…

ABAP学习笔记之——第四章:模块化程序

一、子程序&#xff1a; 语法&#xff1a; 参数&#xff1a; 参数(Parameter)是指调用子程序时用于传入、传出的值。子程序中的参数与一般用 DATA语句定义的局部变量相同。调用子程序时使用的参数叫实参(Actual Parameter)&#xff0c;在子程序中使用的参数叫虚参(Formal Par…

nginx(六十八)http_proxy模块 nginx与上游的ssl握手

一 nginx作为客户端与上游的SSL/TLS握手 理解上&#xff1a; nginx作为客户端,此时类似浏览器的角色,发请求建立连接 nginx作为server端与下游进行SSL/TLS握手 ① nginx与后端选择什么样的协议 1&#xff09;如果nginx与上游是局域网内,一般通过http建立请求,不需要进行…

使用flv.js + websokect播放rtsp格式视频流

1.问题背景 在最近的项目中&#xff0c;涉及到海康接入的视频播放的问题&#xff0c;海康这边获取到的视频流是rtsp格式&#xff0c;web端目前没有直接可以播放的组件&#xff0c;于是最开始是后端处理了视频流&#xff0c;返回hls格式的m3u8地址&#xff0c;这样用videojs插件…

进程【JavaEE初阶】

目录 一、操作系统 二、进程 2.1 进程的概念 2.2 进程的管理 2.3 PCB 2.3.1 PCB里面的一些属性 2.3.2 进程的调度 2.3.3 进程的虚拟地址空间 2.3.4 进程间通信 一、操作系统 CPU、存储器、输入设备、输出设备&#xff0c;这些实物看得着摸得到的&#xff0c;都属于 …

web前端-javascript-switch条件分支语句(语法,执行流程,补充)

文章目录条件分支语句(switch 语句)1. 语法&#xff1b;2. 执行流程&#xff1a;2.1. 在执行时会依次将 case 后的条件表达式的值和 switch 后的条件表达式的值进行全等比较2.2. 如果比较结果为 true&#xff0c;则从当前 case 处开始执行代码2.3. 如果比较结果为 false&#x…

【知识网络分析】研究机构合作网络(co-investigator institution)

研究机构合作网络(co-investigator institution) 1 网络数据集读取2 网络最大子群数据获取与精简3 中心点指定网络半径子群获取4 节点中心度相关指标计算1 网络数据集读取 使用GC.networkCoInvestigatorInstitution()方法快速生成研究结构合作网络数据集,其中GC代表着读入p…

解析华为OSPF协议

文章目录 前言一、pandas是 目录 文章目录 OSPF基础 一、报文类型 二、LSA类型 三.LSA在各区域中传播的支持情况 四.邻居状态机 邻居关系 邻接关系 &#xff18;种状态机&#xff1a; OSPF报文认证 OSPF缺省路由 2.读入数据 总结 什么&#xff1f;二、使用步骤 1.引入库2.读入数…

卷积神经网络CNN各层基本知识

卷积神经网络 卷积神经网络(CNN)由输入层、卷积层、激活函数、池化层以及全连接层构成。 INPUT&#xff08;输入层&#xff09;-CONV&#xff08;卷积层&#xff09;-RELU&#xff08;激活函数&#xff09;-POOL&#xff08;池化层&#xff09;-FC&#xff08;全连接层&#…

[VNCTF2022]easyj4va

看源码 输入 /file?url 1报错 用伪协议可以读取到内容 /file?urlfile:///etc/passwd 然后就是查看java字节码文件的目录 file?urlfile:///usr/local/tomcat/webapps/ROOT/WEB-INF 这里官方给了另外一个协议netdoc&#xff0c;跟file用法是一样的&#xff0c;但是这个netd…

JDK动态代理与Cglib动态代理使用详解

JDK动态代理与Cglib动态代理使用详解一、JDK动态代理准备使用二、Cglib动态代理准备使用Enhancer.create(Class type, Callback callback)Enhancer.create((Class superclass, Class[] interfaces, Callback callback))Enhancer.create(Class superclass, Class[] interfaces, …

【学习笔记35】JavaScript计算两个指定日期的时间差

一、要求 计算两个指定日期的时间差&#xff08;2023年元旦到来的时间&#xff09; 二、分析 先获取到两个时间距离1970&#xff08;格林尼时间&#xff09;~~~毫秒数计算两个毫秒数的差值 ----> 得到了总毫秒数计算总毫秒数内, 有多少个完整的天 parseInt(总毫秒数 / 一天的…

会话跟踪技术-session和cookie

会话&#xff08;Session&#xff09;跟踪是Web程序中常用的技术&#xff0c;用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。 Cookie通过在客户端记录信息确定用户身份&#xff0c;Session通过在服务器端记录信息确定用户身份。 Cookie对象与HttpSession对象简…

nginx(六十七)http_ssl模块 client与nginx的ssl握手

一 HTTPS握手机制 关注点&#xff1a; SSL/TLS握手的细节与nginx配置指令的关系核心&#xff1a; 讲解客户端(下游)与作为server端的nginx之间的握手最佳实践&#xff1a; 建议在http块中通过include ssl.conf把共工部分抽离处理ssl/tls报错原因&#xff1a;可能是客户端或服…

Flutter高仿微信-第56篇-搜索好友

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; /*** Author : wangning* Email : maoning20080809163.co…