由归并算法引申出来的其他问题

简介: 前言:   上一节刚讲过归并算法是排序算法中比较少见的一种时间复杂度为:θ(nlgn)的算法。而归并算法之所以快的原因在于它用了分治的思想,现实生活中有很多需要用到分治思想解决的问题,下面就举两个例子。

前言:

  上一节刚讲过归并算法是排序算法中比较少见的一种时间复杂度为:θ(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

 

黎明前最黑暗,成功前最绝望!
相关文章
|
2月前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
22 0
|
4月前
|
搜索推荐 算法
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数
算法:分治思想处理归并递归问题
算法:分治思想处理归并递归问题
|
5月前
|
搜索推荐 C++ Python
Python排序算法大PK:归并VS快速,谁才是你的效率之选?
【7月更文挑战第13天】归并排序** 使用分治法,稳定且平均时间复杂度O(n log n),适合保持元素顺序和并行处理。
40 5
|
6月前
|
算法 C语言
数据结构和算法——归并排序(有序子列的归并、递归算法、非递归算法、思路图解、C语言代码)
数据结构和算法——归并排序(有序子列的归并、递归算法、非递归算法、思路图解、C语言代码)
37 0
|
搜索推荐 Java
排序算法-冒泡、选择、堆、插入、归并、快速、希尔
排序算法-冒泡、选择、堆、插入、归并、快速、希尔
33 0
|
7月前
|
存储 算法 搜索推荐
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
224 1
|
7月前
|
存储 算法 搜索推荐
【算法系列篇】分治-归并
【算法系列篇】分治-归并
|
7月前
|
算法 搜索推荐
归并算法:分治而治的高效算法大揭秘(图文详解)
归并算法:分治而治的高效算法大揭秘(图文详解)
107 0
|
算法 搜索推荐 前端开发
前端排序算法哪家强:冒泡、选择、插入、归并、快速,哪个才是最强者?
当谈到前端开发时,排序算法是必不可少的一部分。排序算法可以帮助我们对数据进行有效的排序,使其更具有结构和有序性。在前端领域中,有许多常见的排序算法,其中包括冒泡排序、选择排序、插入排序、归并排序和快速排序。让我们一起来了解这些算法以及它们的原理和特点,并通过具体的例子说明它们在实际开发中的应用。
142 0
前端排序算法哪家强:冒泡、选择、插入、归并、快速,哪个才是最强者?