题目:
一个乱序数组a[0…n-1],求a[j]-a[i]的最大值,其中i<j。
一、观察现象
观察一个数组 int a[] = {5,19,40,2,100,844,12,3,6,8,33,90};很明显最大差值应该是844-2=842。我们把数组分为前后两部分,分割位置为元素2的后面。数组分为两个子数组:
int a1[] = {5,19,40,2};
int a2[] = {100,844,12,3,6,8,33,90};
2刚好是a1的最小值,844是a2的最大值。
二、解决办法
我们通过一个k值,从头到尾多次分割数组。
分别求出每个k值对应的两个子数组a1的最小值a1_min,a2的最大值a2_max
最大差值就是a2_max-a1_min的最大值
可以通过反证法证明:
就是说 最大差值的时候,
a[i] 一定是前面半段数组的最小值,如果不是最小值,就应该去用那个最小值了。
a[j]一定是后面半部分的最大值,如果不是最大值,就应该去用那个最大值了
所以结果一定出现在当从某个k的下标分割时,后面的最大值减去前面的最小值。
package gxu.wjb.part1;
import java.util.Arrays;
/**
* 一个乱序数组a[0...n-1],求a[j]-a[i]的最大值,其中i<j
*
*
*
*/
public class Main {
public static int GetMaxDiff(int[] arr) {
int rusult = 0;
int L = 0;
int R = arr.length;
for (int i = 0; i < arr.length - 1; i++) {
int maxDiff = getMax(arr, i + 1, R) - getMin(arr, L, i);
rusult = maxDiff > rusult ? maxDiff : rusult;
}
return rusult;
}
public static int getMax(int[] arr, int L, int R) {
int max = 0;
for (int i = L; i < R; i++) {
max = max > arr[i] ? max : arr[i];
}
return max;
}
public static int getMin(int[] arr, int L, int R) {
int min = arr[L];
for (int i = L; i < R + 1; i++) {
min = min < arr[i] ? min : arr[i];
}
return min;
}
public static void main(String[] args) {
int array[] = { 5, 19, 40, 2, 100, 844, 12, 3, 6, 8, 33, 90 };
int result = GetMaxDiff(array);
System.out.println(result);
}
}
引申题:(大疆2019笔试题)
对于一个长度大于4的数组,存在i, j, p, q, 使得i<j<p<q,且n[j] - n[i] + n[q]-n[p]值最大,求出这个最大值,并说明时间复杂度。
目前只能想到O(n^2)的方法:利用两个数组left,right分别存储从左侧开始遍历任意两个数相减的最大值,从右侧开始遍历任意两个数相减的最大值,最后求解两个数组满足left[k]+right[m]最大(满足k<m)。时间复杂度为O(n^2)