問題描述:最大間隙問題:給定n個實數x1,x2,...,xn,求這n個數在實軸上相鄰2個數之間的最大差值。假設對人格實數的下取整函數耗時O(1),設計解最大間隙的問題的線性時間算法。
算法設計:對於給定的n個實數x1,x2,...,xn,計算它們的最大間隙。
數據輸入:輸入數據由文件名爲input.txt的文本文件提供。文件的第一行有一個正整數n,接下來的一行中有n個實數x1,x2,..,xn。
結果輸出:將找到的最大間隙輸出到文件output.txt。
輸入文本示例 輸出樣本示例
input.txt output.txt
5 3.2
2.3 3.1 7.5 1. 5 6.3
解題思路:
開始時的思想是先排序,再找最大兩個的相鄰數的差值。但是排序的複雜度最好是O(nlogn),達不到線性。
看了一種方法是利用鴿籠原理,感覺很巧妙,先找到最大和最小數,這步複雜度是O(n),接着做最大最小·值得差,再除以n-1得到n-1的籠子,把除最大最小值的n-2的鴿子放進去,一定有一個籠子是空的,在同一個籠子的間距不可能是最大值,最大值一定在不同的兩個籠子中,找到每個籠子的最大值和最小值和鴿子數,從最小的籠子開始找,用後一個有鴿子的籠子的最小值減前面一個有鴿子的籠子的最大值,最後找到最大間距。
main.c
#include<iostream>
#include"fileRW.h"
#define N 100
double MaxCle(int n, double *x);
using namespace std;
int main()
{
int num = 0;
double data[N];
ReadData(&num, data);
double maxCle= MaxCle(num, data);
WriteData(maxCle);
/*
cout << num << endl;
for (int i = 1; i <= num; i++)
{
cout << data[i] << " ";
}
cout << endl;
cout << maxCle << endl;
system("pause");
*/
return 0;
}
// 尋找最小元素的下標
template < class T>
int Mini(int n, T *x)
{
T tmp = x[1];
int k = 1;
for (int i = 1; i <= n; i++)
{
if (x[i] < tmp)
{
tmp = x[i];
k = i;
}
}
return k;
}
// 尋找最大元素的下標
template < class T>
int Maxi(int n, T *x)
{
T tmp = x[1];
int k = 1;
for (int i = 1; i <= n; i++)
{
if (x[i] > tmp)
{
tmp = x[i];
k = i;
}
}
return k;
}
double MaxCle(int n, double *x)
{
// 找到最小最大的值
double minx = x[Mini(n, x)];
double maxx = x[Maxi(n, x)];
//cout << minx << endl;
//cout << maxx << endl;
int *count = new int[n + 1];
double *low = new double[n + 1];
double *high = new double[n + 1];
// 桶初始化
for (int i = 1; i <= n; i++)
{
count[i] = 0;
low[i] = maxx;
high[i] = minx;
}
for (int i = 1; i <= n; i++)
{
// 找到每個元素對應的桶號
int bucket = int((n - 1) * (x[i] - minx) / (maxx - minx)) + 1;
count[bucket]++; // 對應桶的個數增加
// 保存每個桶最小的數
if (x[i] < low[bucket])
{
low[bucket] = x[i];
}
// 保存每個桶最大的元素
if (x[i] > high[bucket])
{
high[bucket] = x[i];
}
}
// 除maxx和minx外的n-2個數放在n-1桶中
// 有鴿舍原理知,有一個桶的空的,最大的間隙不會出現在同一個桶中
double tmp = 0;
double left = high[1];
for (int i = 1; i <= n; i++)
{
//cout << count[i] << endl;
if (count[i])
{
double thisgap = low[i] - left;
if (thisgap > tmp)
{
tmp = thisgap;
left = high[i];
}
}
}
return tmp;
}
fileRW.c
#include "fileRW.h"
// 清空文件
void ClearFile()
{
ofstream ofs;
ofs.open("output.txt", ostream::trunc);/*清空文件*/
ofs.close(); /*關閉文件*/
ofs.clear(); /*清理*/
}
// 寫字符串到文件中
void WriteData(double delta)
{
ClearFile();
ofstream ofs;
ofs.open("output.txt", ostream::app);/*以添加模式打開文件*/
ofs << delta << endl; /*寫入數據*/
ofs.close(); /*關閉文件*/
ofs.clear(); /*清理*/
}