問題描述:給定n個亂序的實數,求這些數在實數軸上相鄰2個數之間的最大差值,假設對任何實數的下取整函數耗時O(1),設計解最大間隙問題的線性時間算法。
思路:如果採用先排序,再求解最大間隙的方式,即使是採用堆排序,解處該問題的複雜度也在O(nlogn)。要在線性時間內求解,可以採用“鴿舍原理”,我們首先找到這組數的最大和最小值,將兩個數之間的數軸分爲n+1份,將這n個數依次放到這n+1個區間中,由“鴿舍原理”可知,其中必有一個區間沒有數,則最大間距應是該區間的前一個區間中最大數與該區間後一個區間中最小數之間的差值。
代碼:
float max_num(float num_arr[], int n) { #找出該組數中最大值。
float temp = num_arr[0];
for (int i = 1;i < n;i++) {
if (temp < num_arr[i]) temp = num_arr[i];
}
return temp;
}
float min_num(float num_arr[], int n) {#找出該組數中最小值。
float temp = num_arr[0];
for (int i = 1;i < n;i++) {
if (temp > num_arr[i]) temp = num_arr[i];
}
return temp;
}
float max_gap(float num_arr[], int n) { #求解最大間隙
float *high = new float[n + 1]; #用於記錄每個區間最大值。n個數,總共n+1個區間。
float *low = new float[n + 1]; #用於記錄每個區間最小值。
int *count = new int[n +1]; #記錄每個區間中數的個數
float max = max_num(num_arr, n);
float min = min_num(num_arr, n);
float dis = max - min;
for (int i = 0;i < n+1;i++) { 對相應值初始化
high[i] =min;
low[i] = max;
count[i] = 0;
}
for (int i = 0;i < n;i++) {
int pos = int((n + 1)*(num_arr[i] - min) / dis); #計算出該數應被分到哪個區#間
count[pos]++;
#更新放入區間的最大最小值
if (high[pos] < num_arr[i])
high[pos] = num_arr[i];
if (low[pos] > num_arr[i])
low[pos] = num_arr[i];
}
float gap = 0;
float low_temp = high[0];
#遍歷區間,找到最大間隙。
for (int i = 1;i < n + 1;i++) {
if (count[i]) {
float gap_temp = low[i] - low_temp;
if (gap_temp > gap) {
gap = gap_temp;
low_temp = high[i];
}
}
}
return gap;
}
int main() {
float num_arr[5] = {2.3, 3.1, 7.5, 1.5, 6.3};
int n = 5;
cout << max_gap(num_arr, n) << endl;
int b;
cin >> b;
}