Java解决计算相邻两个数的最大差值的问题_第1页
Java解决计算相邻两个数的最大差值的问题_第2页
Java解决计算相邻两个数的最大差值的问题_第3页
Java解决计算相邻两个数的最大差值的问题_第4页
Java解决计算相邻两个数的最大差值的问题_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第Java解决计算相邻两个数的最大差值的问题hello,今天给大家带来一道算法题。这道算法题,是我目前为止,见过最难的一道题。那么到底是怎样的一道算法题呢?如下:

题目:给定一个数组,求如果排序之后,相邻两数的最大差值。要求时间复杂度O(N),且要求不能用非基于比较的排序。

我查了一下,暂时没有找到一个在线OJ的链接,只能自己写一个对数器,手动测试了。

当初我看到这个题目的时候,说这怎么可能呢?在一个无序的数组中,求相邻两个数据的最大差值。可是我们都知道,现在基于比较的排序算法,最快也只能够达到O(N*logN)的水平,而题目明确限制时间复杂度要是O(N),所以想通过基于比较的排序,排序之后再进行遍历,时间复杂度肯定是达不到要求的。

有人可能也会想说,不是还有基于非比较的排序算法吗?比如计数排序、基数排序、桶排序。但是题目又明确规定了不能使用基于非比较的排序算法。

这样的话,想使用排序算法,进行排序,这条路肯定是行不通的。只能另外想其他的办法。

-------------------------------------------------------------------------------------------我是分割线-----------------------------------------------------------------------------------------

重头戏来了!!!整个代码的流程如下:

1.先遍历一遍数组,保存整个数组的最大值和最小值。

2.假设数组中一共有N个元素,那么我们就需要准备N+1个桶。

这每一个桶里面,可以存储一定范围内的数值,而具体可以存储多大范围内的数值,需要用公式去计算。比如:第一个桶存储0……9之间的数,第二个桶存储10……19的数……

3.我们再次遍历一遍数组,将每一个数,放入到相应的桶里。

解释:为什么需要进行以上这3个步骤???这是一个非常值得思考的问题!!!

由题可知,一共有N个数,但是我们准备了N+1个桶。也就是说我们将每个数放入相应的桶中,就算这N个数都在各自的桶里,无论怎么放入,始终会多出来1个空桶。

而我们会根据一下这个公式,将每个数放入相应的桶:(arr[i]-min)*N/(max-min)。

以上这个公式,就能够计算出i位置的数,应该放入哪一个桶里。根据公式计算,最小值一定会放到第一个桶里,最大值也一定会放到最后一个桶里。那么既然第一个和最后一个桶肯定是有数据的,也就是说明那个空桶肯定是中间的某一个桶。

正是因为这个空桶的存在,会将很多种计算的可能性直接抹杀掉。说的具体点,假设一个桶的存储数的范围是0~9,也就是这个桶能够存储10个数,既然有一个空桶的话,那么肯定最后的答案是大于10的。

那么既然大于10的话,这两个数肯定不会在同一个桶里。这样的话,我们就排除了桶里面两个数据的情况,只需要考虑相邻两个桶之间的数,才可能是最终的答案。

就如上图的形式,将所有的数据都放入相应的桶里。因为有空桶的存在,所以我们的答案必然是在两个不同桶之间的数据进行相减。而我们在进行相减的时候,只需要记录每个桶的最大值和最小值即可。也就是说,用后一个桶的最小值,减前一个桶的最大值。以这样的形式,循环N次,将每两个相邻的桶进行计算,就能得到最终的答案。

既然我们只需要每个桶里的最大值和最小值,那就准备两个数组maxs和mins,分别存储即可。代码如下:

以上就是这道题的所有代码,代码不多,但是其中的算法思想我觉得真的是很厉害,很难想象出,想到这个方法的是什么人。

核心就在于那个空桶的存在,抹杀很多的可能性。使其最终的答案只可能存在于相邻两个桶之间的数。

提问:假设给定的某一个数组,算出来桶的数据后,只有一个是空桶。那么最终的答案就一定是这个空桶右边桶的数据减去左边桶的数据吗?

最后,我将整个代码全部放到下面,包括了一个对数器,用于测试以上代码的正确性。

importjava.util.Arrays;

publicclassCode01_CalcTwoNumDiv{

publicstaticvoidmain(String[]args){

inttestTime=5000;//测试次数

intN=50;//数组长度

intrange=1000;//数据范围

booleanflag=true;

for(inti=0;itestTime;i++){

int[]arr=generateArr(N,range);

intp1=calcTwoNumDiv(arr);

intp2=sortAfter(arr);

if(p1!=p2){

flag=false;

break;

System.out.println(flag"正确":"错误");

publicstaticintcalcTwoNumDiv(int[]array){

if(array==null||array.length2){

return0;

intmax=Integer.MIN_VALUE;

intmin=Integer.MAX_VALUE;

for(inti:array){//先遍历一遍数组,求最大值最小值

max=Math.max(max,i);

min=Math.min(min,i);

if(max==min){

return0;//如果最大值和最小值相等,说明这个数组只有这一个数据

intlen=array.length;

boolean[]hasNum=newboolean[len+1];

int[]maxs=newint[len+1];

int[]mins=newint[len+1];

//遍历数据

for(inti=0;iarray.length;i++){

intbit=getBit(array[i],len,max,min);//桶的位置

maxs[bit]=hasNum[bit]Math.max(maxs[bit],array[i]):array[i];//更新最大值

mins[bit]=hasNum[bit]Math.min(mins[bit],array[i]):array[i];//更新最小值

hasNum[bit]=true;//始终更新为true

//第一个桶和最后一个桶,肯定是有数据的。

intpreMax=maxs[0];

intres=Integer.MIN_VALUE;//最终的结果

for(inti=1;i=len;i++){

if(hasNum[i]){

res=Math.max(res,mins[i]-preMax);

preMax=maxs[i];//更新前一个的最大值

returnres;

publicstaticintgetBit(intnum,intlen,intmax,intmin){

return((num-min)*len)/(max-min);//计算num应该存储在哪个桶

publicstaticintsortAfter(int[]arr){

if(arr==null||arr.length2){

return0;

Arrays.sort(arr);

intres=Integer.MIN_VALUE;

for(inti=1;iarr.length;i++){

res=Math.max(res,arr[i]-arr[i-1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论