【左神算法】給定一個數組,求如果排序之後,相鄰兩數的最大差值,要求時間複雜度O(N),且要求不能用非基於比較的排序。

1.題目

給定一個數組,求如果排序之後,相鄰兩數的最大差值,要求時間複雜度O(N),且要求不能用非基於比較的排序。

2.實現

2.1 思路

    問題:
 *      給定一個數組,求如果排序之後,相鄰兩數的最大差值,要求時間複雜度O(N),且要求不能用非基於比較的		排序。 
 *      比如 數組[1,2,9,4,6] sort後 [1,2,4,6,9] 6-9之間間隙最大值就爲3. 
 *  思路:
 *      我們可以基於桶排序的思想來解決這個問題。data[1,2,3,4,5,7,8] 那麼最大值就爲2 5->7之間的最大間隙爲2
 *      a.首先創建一個n+1 大小的桶,遍歷一遍數組 找出minValue 和 maxValue。如果最大值和最小值相等 說明數據一樣 直接返回
 *      將minValue放在下標爲0的桶的位置   maxValue放在下標爲n的桶位置。
 *      b.創建三個數組 分別記錄 存放的是hasNum->是否有數據  minNum ->最小值  maxNum ->最大值
 *      遍歷將數據放在每個桶的位置上,桶只存儲三個屬性,是否有數據 最小值 最大值。
 *      c.如此 如果想找出間隙最大值,試想是不可能出現在同一個桶類,只會在相鄰桶之間 也就是 左桶的最大值 和 油桶的 最小值
 *
 *  複雜度分析
 *     time : O(n)
 *     space : O(1)

2.2 code

package com.ncst.base.one;

/**
 * @author i
 * @create 2020/5/9 19:29
 * @Description
 *
 *  問題:
 *      給定一個數組,求如果排序之後,相鄰兩數的最大差值,要求時間複雜度O(N),且要求不能用非基於比較的排序。
 *  思路:
 *      我們可以基於桶排序的思想來解決這個問題。data[1,2,3,4,5,7,8] 那麼最大值就爲2 5->7之間的最大間隙爲2
 *      a.首先創建一個n+1 大小的桶,遍歷一遍數組 找出minValue 和 maxValue。如果最大值和最小值相等 說明數據一樣 直接返回
 *      將minValue放在下標爲0的桶的位置   maxValue放在下標爲n的桶位置。
 *      b.創建三個數組 分別記錄 存放的是hasNum->是否有數據  minNum ->最小值  maxNum ->最大值
 *      遍歷將數據放在每個桶的位置上,桶只存儲三個屬性,是否有數據 最小值 最大值。
 *      c.如此 如果想找出間隙最大值,試想是不可能出現在同一個桶類,只會在相鄰桶之間 也就是 左桶的最大值 和 油桶的 最小值
 *
 *  複雜度分析
 *     time : O(n)
 *     space : O(1)
 */
public class MaxGap {


    public static int maxGap(int[] arr) {
        //1.參數判斷
        if (arr == null || arr.length <= 2) {
            return 0;//表示沒有
        }
        int minValue = Integer.MIN_VALUE;
        int maxValue = Integer.MAX_VALUE;

        //2.遍歷元素 找出minValue 和 maxValue
        for (int value : arr) {
            minValue = Math.min(minValue, value);
            maxValue = Math.max(maxValue, value);
        }

        if (maxValue == minValue) {
            return 0;
        }

        //3.比較 找出間隙最大值
        int n = arr.length;
        boolean[] hasNum = new boolean[n + 1];
        int[] maxNum = new int[n + 1];
        int[] minNum = new int[n + 1];
        //3.1 將每個元素存儲到所屬的桶內
        //記錄桶的下標
        int bid = 0;

        for (int i = 0; i < n; i++) {
            bid = bucket(arr[i], n, minValue, maxValue);
            //找到最小值
            minNum[bid] = hasNum[bid] ? Math.min(arr[i], minNum[bid]) : arr[i];
            //找到最大值
            maxNum[bid] = hasNum[bid] ? Math.max(arr[i], maxNum[bid]) : arr[i];
            hasNum[bid] = true;
        }
        //3.2 找到間隙最大值
        int res = 0;
        int lastIndex = maxNum[0];
        for (int i = 1; i <= n; i++) {
            if (hasNum[i]) {
                res = Math.max(res, minNum[i] - lastIndex);
                lastIndex = maxNum[i];
            }
        }
        return res;
    }

    /***
     *
     * @param num
     * @param len
     * @param min
     * @param max
     * @return
     */
    public static int bucket(long num, long len, long min, long max) {
        return (int) ((num - min) * len / (max - min));
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章