线性时间求解 最大间隙问题

问题描述:给定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;
}

 

你可能感兴趣的:(算法题)