由归并算法引申出来的其他问题
前言:
上一节刚讲过归并算法是排序算法中比较少见的一种时间复杂度为:θ(nlgn)的算法。而归并算法之所以快的原因在于它用了分治的思想,现实生活中有很多需要用到分治思想解决的问题,下面就举两个例子。
问题一:
给定一个整数数组和任意整数,找到数组中是否有两数的和等于给定的整数。
这个问题如果采用穷举法,则大致思路是这样:首先数组的第一个元素与数组剩下的元素相加,看是否有对应的结果。然后再数组第二个元素与除第一个元素和第二个元素本身之外的元素相加... 后面的操作一次类推。很容易得到时间复杂度为:(n-1) + (n-2) + ... + 1 = θ(n2) 。 但其实我们可以借鉴前面归并排序的思想,先对数组进行排序,排完序之后在进行和判断,这时候只要收尾两端各取一个数。如果两数之后大于要找的数,则说明尾数应该前移,如果小于要找的数,则说明前面的数应该后移,如果相等则输出找到的信息,并且避免死循环可以将前一个数后移或者后一个数前移。
java代码如下:
1 public class FindEqualSum { 2 3 public static void main(String[] args) { 4 int[] arr = { 2, 1, 21, 16, 32, 35, 45, 31 }; 5 findEqualSum(arr, 33); 6 } 7 8 private static void findEqualSum(int[] arr, int num) { 9 int startIndex = 0; 10 int endIndex = arr.length - 1; 11 12 // 先进行归并排序,然后再找两数之和 13 divideSort(arr, startIndex, endIndex); 14 findInSorted(arr, startIndex, endIndex, num); 15 } 16 17 private static void divideSort(int[] arr, int startIndex, int endIndex) { 18 if (startIndex >= endIndex) { 19 return; 20 } 21 int midIndex = (startIndex + endIndex) / 2; 22 divideSort(arr, startIndex, midIndex); 23 divideSort(arr, midIndex + 1, endIndex); 24 merge(arr, startIndex, midIndex, endIndex); 25 } 26 27 private static void findInSorted(int[] arr, int startIndex, int endIndex, 28 int num) { 29 int i = startIndex; 30 int j = endIndex; 31 while (i < j) { 32 if (arr[i] + arr[j] > num) { // 如果两数之和大于要找的数说明有一个数过大,这时候需要前移后面较大的数 33 j--; 34 } else if (arr[i] + arr[j] < num) { // 如果两数之和小于要找的数,说明有一个数要小,这时应该后移前面较小的数 35 i++; 36 } else { // 相等这输出找到的信息,这时候如果需要找到所有需要记住仍要前移后一个数或者后移前一个数,防止死循环。 37 System.out.println(arr[i] + " + " + arr[j] + " = " 38 + (arr[i] + arr[j])); 39 j--; 40 } 41 } 42 } 43 44 private static void merge(int[] arr, int startIndex, int midIndex, 45 int endIndex) { 46 int k = 0; 47 int i = startIndex; 48 int j = midIndex + 1; 49 int[] newArr = new int[endIndex - startIndex + 1]; 50 while (i <= midIndex && j <= endIndex) { 51 if (arr[i] > arr[j]) { 52 newArr[k++] = arr[j++]; 53 } else { 54 newArr[k++] = arr[i++]; 55 } 56 } 57 58 if (i <= midIndex) 59 { 60 System.arraycopy(arr, i, newArr, k, midIndex - i + 1); 61 } 62 if (j <= endIndex) 63 { 64 System.arraycopy(arr, j, newArr, k, endIndex - j + 1); 65 } 66 System.arraycopy(newArr, 0, arr, startIndex, endIndex - startIndex + 1); 67 } 68 69 }
FindEqualSum.java
问题二:
假设数组A[n],对于其中的A[i]和A[j],如果i<j, A[i] > A[j].则称两个元素为数组中的逆序对。求任意给定数组的所有逆序对。
同样的道理:可以通过归并排序的排序过程来进行逆序判断,只要在merge的过程中进行对比就行了。
1 private static void merge(int[] arr, int startIndex, int midIndex, 2 int endIndex) { 3 int k = 0; 4 int i = startIndex; 5 int j = midIndex + 1; 6 int[] newArr = new int[endIndex - startIndex + 1]; 7 while (i <= midIndex && j <= endIndex) { 8 if (arr[i] > arr[j]) { 9 count++; // 这里用来记录逆序对的个数 10 newArr[k++] = arr[j++]; 11 } else { 12 newArr[k++] = arr[i++]; 13 } 14 } 15 16 if (i <= midIndex) 17 { 18 System.arraycopy(arr, i, newArr, k, midIndex - i + 1); 19 } 20 if (j <= endIndex) 21 { 22 System.arraycopy(arr, j, newArr, k, endIndex - j + 1); 23 } 24 System.arraycopy(newArr, 0, arr, startIndex, endIndex - startIndex + 1); 25 }
FindReverse
黎明前最黑暗,成功前最绝望!
由归并算法引申出来的其他问题相关推荐
- 基于Fork/Join框架实现对大型浮点数数组排序(归并算法和插入排序算法)
分支/合并框架 说明 重点是那个浮点数数组排序的例子,从主函数展开,根据序号看 1.GitHub代码欢迎star.你们轻轻的一点,对我鼓励特大,我有一个习惯,看完别人的文章是会点赞的. 2.个人认为学 ...
- python分割数字_对python数据切割归并算法的实例讲解
当一个 .txt 文件的数据过于庞大,此时想要对数据进行排序就需要先将数据进行切割,然后通过归并排序,最终实现对整体数据的排序.要实现这个过程我们需要进行以下几步:获取总数据行数:根据行数按照自己的需 ...
- 归并算法(分割与合并)
归并算法也是一种分治法,分治法与递归求科赫曲线,是递归变化的一种高级排序! #include <iostream> #include<stdio.h> #include< ...
- 基于Fork/Join框架实现对大型浮点数数组排序(归并算法和插入排序算法) 1
分支/合并框架 说明 重点是那个浮点数数组排序的例子,从主函数展开,根据序号看 1.GitHub代码欢迎star.你们轻轻的一点,对我鼓励特大,我有一个习惯,看完别人的文章是会点赞的. 2.个人认为学 ...
- 【数据结构笔记35】C实现:有序子列的归并算法:递归与非递归的实现
本次笔记内容: 9.4.1 有序子列的归并 9.4.2 归并算法 9.4.3 非递归算法 文章目录 归并排序的核心:两个有序子列的归并 归并算法实现策略一:递归算法 注意要有统一函数接口 为什么要有参 ...
- 链表排序---迭代版本归并算法 + [leetcode]148. 排序链表
前言: 对于链表来说,排序首选应该是归并算法 维基百科上有归并算法的迭代版本和递归版本 基于数组实现的. https://zh.wikipedia.org/wiki/%E5%BD%92%E5%B9%B ...
- 归并排序时间复杂度_一文带你读懂排序算法(四):归并算法
点击上方蓝字关注我们 归并排序的基本思想核心是分治,就是把一个复杂的问题分成两个或多个相同或相似的子问题,然后把子问题分成更小的子问题,直到子问题可以简单的直接求解,最原问题的解就是子问题解的合并.算 ...
- 归并算法(Java)
归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法. 把长度为n的输入序列分成两个长度为n/2的子序列: 对这两个子序列分别采用归并排序: 将两个排序好的子序列合并成一 ...
- [HIT-DB-Lab3] 数据库的多路归并算法及其实现
HIT战德臣老师的数据库lab3, 目的是用代码实现一个两阶段多路归并算法, 处理数据, 具体要求如下 目的 思路 先看看ppt上有关内容: 两趟多路归并算法其实不难理解, 如果你的内存足够大, 你可 ...
最新文章
- OpenCV | OpenCV检测图像轮廓
- 谷歌眼镜开发入门经典
- 时讯无线为你提供快速的上网设备
- 程序员的杂想-不要只做一名程序员
- Linux环境下Redmine的安装(一)
- Libevent事件的创建-scoke服务的创建-特征的获取和配置
- android 图片跑马灯动画,ImageView 图片循环跑马灯的效果
- android 多线程 场景,精选Android初中级面试题 (三): 深探Handler,多线程,Bitmap
- 没有残差连接的ViT准确率只有0.15%!北大华为提出用于ViT的增强 Shortcuts,涨点显著!...
- 什么是反向跟单?反向跟单怎么运作?
- 注册表禁用计算机管理,Win7注册表编辑器被管理员禁用的解除方法
- banq修复_慧荣SM3271AB U盘量产加密及修好图文详细教程
- asp.net 获得根文件夹在服务器上物理路径,asp.net获取网站目录物理路径示例
- 永远保持一颗奋斗的心
- 聊聊支付通道那些事儿——介绍和接入
- 用3dmax调整obj
- golang开发工程师-第一步:golang入门基础教学
- 极大似然估计原理思想
- kibana KQL语法实例
- 《An Industrial-Strength Audio Search Algorithm》译文