letcode 164求最大間距(鴿巢原理)

2021-10-01 11:43:00 字數 3220 閱讀 8376

給定乙個無序的陣列,找出陣列在排序之後,相鄰元素之間最大的差值。

如果陣列元素個數小於 2,則返回 0。

輸入: [3,6,9,1]

輸出: 3

解釋: 排序後的陣列是 [1,3,6,9], 其中相鄰元素 (3,6) 和 (6,9) 之間都存在最大差值 3。

輸入: [10]

輸出: 0

解釋: 陣列元素個數小於 2,因此返回 0。

我們知道如果是有序陣列的話,我們就可以通過計算兩兩數字之間差即可解決問題。

那麼如果是更巨集觀上的有序呢?

我們可以只計算相鄰箱子 min 和 max 的差值來解決問題嗎?空箱子直接跳過。

第 2 個箱子的 min 減第 0 個箱子的 max, 23 - 6 = 17

第 3 個箱子的 min 減第 2 個箱子的 max, 33 - 29 = 4

看起來沒什麼問題,但這樣做一定需要乙個前提,因為我們只計算了相鄰箱子的差值,沒有計算箱子內數字的情況,所以我們需要保證每個箱子裡邊的數字一定不會產生最大 gap。

我們把箱子能放的的數字個數記為 interval給定的數字中最小的是 min,最大的是 max。那麼箱子劃分的範圍就是 min ~ (min + 1 * interval - 1)、(min + 1 * interval) ~ (min + 2 * interval - 1)、(min + 2 * interval) ~ (min + 3 * interval - 1)…,上邊舉的例子中, interval 我們其實取了 10。

劃定了箱子範圍後,我們其實很容易把數字放到箱子中,通過(nums[i] - min) / interval即可得到當前數字應該放到的箱子編號。那麼最主要的問題其實就是怎麼去確定 interval。

interval 過小的話,需要更多的箱子去儲存,很費空間,此外箱子增多了,比較的次數也會增多,不划算。

interval 過大的話,箱子內部的數字可能產生題目要求的最大 gap,所以肯定不行。

所以我們要找到那個保證箱子內部的數字不會產生最大 gap,並且盡量大的 interval。

繼續看上邊的例子,0 3 4 6 23 28 29 33 38,陣列中的最小值 0 和最大值 38 ,並沒有參與到 interval 的計算中,所以它倆可以不放到箱子中,還剩下 n - 2 個數字。

像上邊的例子,如果我們保證至少有乙個空箱子,那麼我們就可以斷言,箱子內部一定不會產生最大 gap。

因為在我們的某次計算中,會跳過乙個空箱子,那麼得到的 gap 一定會大於 interval,而箱子中的數字最大的 gap 是 interval - 1。

接下來的問題,怎麼保證至少有乙個空箱子呢?

鴿巢原理的變形,有 n - 2 個數字,如果箱子數多於 n - 2 ,那麼一定會出現空箱子。總範圍是 max - min,那麼 interval = (max - min) / 箱子數,為了使得 interval 盡量大,箱子數取最小即可,也就是 n - 1。

所以 interval = (max - min) / n - 1 。這裡如果除不盡的話,我們 interval 可以向上取整。因為我們給定的數字都是整數,這裡向上取整的話對於最大 gap 是沒有影響的。比如原來範圍是 [0,5.5),那麼內部產生的最大 gap 是 5 - 0 = 5。現在向上取整,範圍變成[0,6),但是內部產生的最大 gap 依舊是 5 - 0 = 5。

public

intmaximumgap

(int

nums)

int n = nums.length;

int min = nums[0]

;int max = nums[0]

;//找出最大值、最小值

for(

int i =

1; i < n; i++)if

(max - min ==0)

//算出每個箱子的範圍

int interval =

(int

) math.

ceil((

double

)(max - min)

/(n -1)

);//每個箱子裡數字的最小值和最大值

int[

] bucketmin =

newint

[n -1]

;int

bucketmax =

newint

[n -1]

;//最小值初始為 integer.max_value

arrays.

fill

(bucketmin, integer.max_value)

;//最小值初始化為 -1,因為題目告訴我們所有數字是非負數

arrays.

fill

(bucketmax,-1

);//考慮每個數字

for(

int i =

0; i < nums.length; i++

)//更新當前數字所在箱子的最小值和最大值

bucketmin[index]

= math.

min(nums[i]

, bucketmin[index]);

bucketmax[index]

= math.

max(nums[i]

, bucketmax[index]);

}int maxgap =0;

//min 看做第 -1 個箱子的最大值

int previousmax = min;

//從第 0 個箱子開始計算

for(

int i =

0; i < n -

1; i++

)//當前箱子的最小值減去前乙個箱子的最大值

maxgap = math.

max(bucketmin[i]

- previousmax, maxgap)

; previousmax = bucketmax[i];}

//最大值可能處於邊界,不在箱子中,需要單獨考慮

maxgap = math.

max(max - previousmax, maxgap)

;return maxgap;

164 最大間距

給定乙個無序的陣列,找出陣列在排序之後,相鄰元素之間最大的差值。如果陣列元素個數小於 2,則返回 0。示例 1 輸入 3,6,9,1 輸出 3 解釋 排序後的陣列是 1,3,6,9 其中相鄰元素 3,6 和 6,9 之間都存在最大差值 3。思路 注釋 public static int maximu...

164 最大間距

開始想的是計數排序,但超時,如 2,999999999 這樣的樣例,記錄陣列太長,有用的佔比太少。後看官方思路,用n 1 n為原陣列元素個數 個桶去篩元素,每個桶能放的元素大小範圍固定,即下面 中的step,處理完後再掃瞄一遍當前桶最大和後繼桶最小值的差,取最大差值為結果。至於為什麼要n 1個桶,我...

164 最大間距

題目.high 對於整數型的排序問題,首先應該聯想到桶排序,這是唯一on的排序演算法。另外假設我們把n個數放在n 1個桶裡面,必定有空桶產生,那麼最大間距肯定在間隔了空桶的兩個桶之間產生 package main import fmt type bucket struct func maximumg...