天天看点

数组中最大间距问题

问题描述:给一个无序的数组,要求在O(n)的时间内求出排完序后相邻两数的最大间距,不许用桶排。

题解:

        用分桶法来做。

        先求出数组的最大最小值,然后给每个元素分桶。分桶的计算公式为:(cur-min)*n/(max-min)

        这样就能保证正好有n+1个桶(从0到n),对于每个桶只维护其最大最小值,以及里面是否有值。

       由于n个数放n+1个桶,必然有一个空桶,所以最大间距必然出现在空桶的左右两边。(空桶一定不会是最后一个或者第一个,因为min和max分占两桶)。

import java.util.Scanner;

public class maxgap {
	public static int maxGap(int[] num) {
		int len = num.length;
		int min = Integer.MAX_VALUE;
		int max = Integer.MIN_VALUE;
		for(int i=0;i<len;i++) {
			min = Math.min(min,num[i]);
			max = Math.max(max,num[i]);
		}
		if(min==max)
			return 0;
		boolean[] vis = new boolean[len+1];
		int[] mins = new int[len+1];
		int[] maxs = new int[len+1];
		int bid = 0;
		for(int i=0;i<len;i++) {
			bid = bucket(num[i],min,max,len);//如何证明一个桶内的值肯定不会是最大间距的值
			mins[bid] = vis[bid]?Math.min(mins[bid], num[i]):num[i];
			maxs[bid] = vis[bid]?Math.max(maxs[bid], num[i]):num[i];
			vis[bid] = true;
		}
		int ans = 0;
		int lastmax = maxs[0];
		for(int i=1;i<=len;i++) {
			if(vis[i]) {
				ans = Math.max(ans, mins[i]-lastmax);
				lastmax = maxs[i];
			}
		}
		return ans;
	}
	
	public static int bucket(int cur,int min,int max,int len) {
		return (int) ((cur-min)*len/(max-min));
	}
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n;
		n = in.nextInt();
		int[] a = new int[n];
		for(int i=0;i<n;i++)
			a[i] = in.nextInt();
		int ans = maxGap(a);
		System.out.println(ans);
	}
}