面试题:一个乱序数组a[0...n-1],求a[j]-a[i]的最大值

题目:

一个乱序数组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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值