最大间隙问题

   问题描述:给定n个实数,求这些实数在实数见不鲜上相邻两个数之间的最大差值。假设对任何实数的下取整函数耗时O(1),试设计最大间隙问题的线性时间算法。   

    解题思路:该问题其实并不复杂,最简单的思路是将给定的数进行排序,然后将排序后的数组扫描一下,得到两个数之间的最大间隙即可。问题复杂在要求的时间复杂度上,要求在O(1)时间内完成,这就要求对输入的数字扫描的次数不能超过N次,为此,可以采取鸽笼原理来进行。假设输入了N个数字,降去最大和最小两个元素外,还剩余N-2个元素,如果将这N-2个数字分配到N-1个区间里,则至少有一个空区间。而分配在区间内部两个元素的差一定小于区间的宽度,因此,最大间隙是一定存在的。而在处理区间时,需要记录三方面的东西:(1)区间内存储元素的数目;(2)区间的下限;(3)区间的上限。


参考程序 :


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class Section1_5 {


public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入值的个数:");
int num;
num = scan.nextInt();
System.out.println("请输入要比较的数:");
double arr[] = new double[num];
for (int i = 0; i < num; i++) {
arr[i] = scan.nextDouble();
}
DealNum d = new DealNum();
double[] array = d.order(arr);// 存放最大最小两个端点的数组
Region r = new Region();
float result = (float)r.compare(r.distribute(arr, r.divide(array, num), array));
System.out.println(result);
}
}


class Region {
double left;// 下限
// int right;//上限
double low;// 区间最大值
double high;// 区间最小值
double length;// 区间长度
int count;// 区间内数字个数
List<Region> list;


// 无参构造函数
public Region() {


}


// 带参构造函数
public Region(double left, double low, double high, double length) {
this.left = left;
this.low = low;
this.high = high;
this.length = length;
}


/**
* 将区间划分出来

* @param arr []为求得的包含最大与最小值得数组,length为输入的数字个数
* @author LiuYong
* @version 2013-9-4 下午12:05:24
*/
public List<Region> divide(double[] arr, int length) {
double len = 0;// 间距大小
list = new ArrayList<Region>();
len = (arr[1] - arr[0]) / (length - 1);
for (int i = 0; i < length - 1; i++) {
Region r = new Region(arr[0] + len * i, 0, 0, len);
list.add(r);
}
return list;
}


/**
* 分配数组中的数

* @param arr []代表需要比较的数组 list代表区间对象链表, min代表最小值
* @author LiuYong
* @version 2013-9-4 下午2:04:57
*/
public List<Region> distribute(double[] arr, List<Region> list, double[] array) {
int j = 0;
int i = 0;
while (j <= list.size()) {
i = (int) ((arr[j] - array[0]) / list.get(0).length);
if (i == list.size()) {
i = i - 1;
}
if (list.get(i).count != 0) {
if (arr[j] > list.get(i).high) {
list.get(i).high = arr[j];
list.get(i).count++;
j++;

if (arr[j] < list.get(i).low) {
list.get(i).low = arr[j];
list.get(i).count++;
j++;
}
} else {
list.get(i).low = arr[j];
list.get(i).high = arr[j];
list.get(i).count++;
j++;
}
}
return list;
}


public double compare(List<Region> list) {
double gap = 0;
double tempgap = 0;
double low=0;
double high=list.get(0).high;
for (int i = 1; i < list.size() ; i++) {
if(list.get(i).count!=0){
low=list.get(i).low;
tempgap = low - high;// 用后一个区间的最小值减前一个区间的最大值,得出第一个间隙
gap = gap < tempgap ? tempgap : gap;
high=list.get(i).high;
}
}
return gap;
}
}


class DealNum {
/**
* 找到最大最小值

* @author LiuYong
* @version 2013-9-4 上午11:49:02
*/
public double[] order(double[] arr) {
double mintemp = arr[0];
double maxtemp = arr[0];
double[] array = new double[2];
for (int i = 0; i < arr.length; i++) {
if (mintemp > arr[i]) {
mintemp = arr[i];
}
if (maxtemp < arr[i]) {
maxtemp = arr[i];
}
array[0] = mintemp;
array[1] = maxtemp;
}
return array;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值