1-5 最大间隙问题
问题描述
给定 n 个实数,求这n个实数在数轴上相邻2个数之间的最大差值,设计解最大间隙问题的线性时间算法。
分析
可用抽屉原理设计最大间隙问题的线性时间算法。
Java
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
//case 1: max gap is 6.3 -3.1 = 3.2
double[] numbers = {2.3, 3.1, 7.5, 1.5, 6.3};
//case 2: max gap is 7.5 - 3.2 = 4.3
// double[] numbers = {2.3, 3.1, 7.5, 1.5, 3.2};
//case 3: max gap is 6.1 - 1.5 = 4.6
// double[] numbers = {6.1, 6.1, 7.5, 1.5, 6.3};
//case 4: max gap is 7.5 - 5.2 = 2.3
// double[] numbers = {2.3, 3.1, 7.5, 1.5, 5.2};
int n = numbers.length;
double maxGap = getMaxGap(n, numbers);
System.out.println("The max gap is: "+maxGap);
}
private static double getMaxGap(int n, double[] numbers){
double minNum = getMinNum(numbers);
double maxNum = getMaxNum(numbers);
int[] count = new int[n+1];//实际分到每个桶的数据个数
double[] low = new double[n+1];//实际分到每个桶的最小数据
double[] high = new double[n+1];//实际分到每个桶的最大数据
//初始化桶
for(int i=1; i<=n-1; i++){
count[i] = 0;
low[i] = maxNum;
high[i] = minNum;
}
//将n个数放入n-1个桶中
for(int i=1; i<=n; i++){
//按如下规则将numbers[i-1]分配到某个桶(编号bucket)中
//若numbers[i-1]=minNum,则被分到第1个桶中(minNum即为桶1的下界也即左界)
int bucket = (int) ((n-1)*(numbers[i-1]-minNum)/(maxNum-minNum)) + 1;//桶编号
//若numbers[i-1]=maxNum,则被分到桶n中(maxNum为桶n的下界也即左界桶n-1的上界也即右界)
//但没有桶n,此时可人为将其移入桶n-1中
if(bucket == n)
bucket--;
count[bucket]++;
if(numbers[i-1] < low[bucket])
low[bucket] = numbers[i-1];
if(numbers[i-1] > high[bucket])
high[bucket] = numbers[i-1];
}
//此时,除最大最小数据maxNum和minNum以外的n-2个数据被放入n-1个桶中
//由抽屉原理可知至少有一个桶是空的
//又因每个桶的大小相同,所以最大间隙不会在同一桶中出现
//一定是某个桶的上界即右界(high)和其后某个桶的下界即左界(low)之间隙
//注意:该两桶之间的桶(即编号在该两桶编号之间的桶)一定是空桶
//即最大间隙在桶i的上界和桶j的下界之间产生(j>=i+1)
double tmpGap = 0, left = high[1];
for(int i=2; i<=n-1; i++){
if(count[i] > 0){
// double thisGap = low[i] - left;
double thisGap = sub(low[i], left);
if(thisGap > tmpGap)
tmpGap = thisGap;
left = high[i];
}
}
return tmpGap;
}
//get the min number
private static double getMinNum(double[] numbers){
double temp = numbers[0];
for(int i=0; i<numbers.length; i++){
if(numbers[i] < temp)
temp = numbers[i];
}
return temp;
}
//get the max number
private static double getMaxNum(double[] numbers){
double temp = numbers[0];
for(int i=0; i<numbers.length; i++){
if(numbers[i] > temp)
temp = numbers[i];
}
return temp;
}
/**
* 提供精确的减法运算。
*
* @param value1 被减数
* @param value2 减数
* @return 两个参数的差
*/
private static double sub(Double value1, Double value2) {
BigDecimal b1 = new BigDecimal(Double.toString(value1));
BigDecimal b2 = new BigDecimal(Double.toString(value2));
return b1.subtract(b2).doubleValue();
}
}
Case 1 output
The max gap is: 3.2
Case 2 output
The max gap is: 4.3
Case 3 output
The max gap is: 4.6
Case 4 output
The max gap is: 2.3
Reference
王晓东《计算机算法设计与分析》(第3版)P8