算法设计与分析: 1-5 最大间隙问题

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

猜你喜欢

转载自blog.csdn.net/ioio_/article/details/80947908