由归并算法引申出来的其他问题
时间:2022-05-04
本文章向大家介绍由归并算法引申出来的其他问题,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
前言:
上一节刚讲过归并算法是排序算法中比较少见的一种时间复杂度为:θ(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 }
问题二:
假设数组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 }
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 蓝桥杯 1的个数
- 蓝桥杯-试题 算法训练 数据交换
- 解决mysql导入新数据库大小写问题(Table 'zup.Domain_System' doesn't exist)
- 蓝桥杯vip试题 报时助手
- 蓝桥杯-基础练习 查找整数
- 蓝桥杯-基础练习 数列排序
- 无线网络-何为ISM频段?
- 蓝桥杯vip测试题系统试题-算法提高 矩阵转置
- 蓝桥杯vip测试题系统-数组求和(解题思路以及解题代码,手画思路图虽然丑丑的)
- 蓝桥杯vip测试题-找零钱(解题思路以及解题代码)
- 剑指Office-二进制中1的个数
- 剑指Office-旋转数组的最小数
- Mysql调优你不知道这几点,就太可惜了
- Mysql快速导入数百万条数据,亲测有效
- [面试题06]从未到头打印链表(LeetCode-剑指Offer)