最大間隙問題

問題描述:最大間隙問題:給定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(); /*清理*/

}



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