leetcode164-无序数组排序后的最大相邻差值

在这里插入图片描述
刷这道题是因为网上一篇文章《漫画算法:无序数组排序后的最大相邻差值》感兴趣,其中方法一先排序,遍历求解时间复杂度为N*log(N)过高不合适,方法二用计数法因为空间复杂度过高也不合适,方法三用到的同桶排序,看文章的时候觉得非常合理,现实刷题过程中发现文章有很多的细节问题,比如作者认为桶的个数为len+1,最大距离必定产生在一个空桶的左右,这些只有在刷题的过程中才会发现细节问题。本题最大的一个思路就是保证最大距离在桶间,而不是桶内,最小的值放第一个桶,最大的值放最后一个桶。笔者认为刷题还是自己动手写下代码才能感受到其中的细节和体会到里面的乐趣。本题的很多细节放在代码注释中,读者可以根据代码和注释慢慢理解、解决本题。

package no151_200;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class subject164 {
	/**
	 * 
	 * @author cehkongfu
	 * @time 2019.06.04 20:30~22:00
	 *
	 */
	class Solution {
		public int maximumGap(int[] nums) {
			int len = 0;
			//数据预处理:对数据进行去重
			HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
			for(int i=0; i<nums.length; i++) {
				if(!map.containsKey(nums[i])) {
					map.put(nums[i], 1);
					len++;
				}else {
					map.put(nums[i], map.get(nums[i])+1);
				}
			}
			int[] noRepeatNums = new int[len];
			int index=0;
			for(Integer key:map.keySet()) {
				noRepeatNums[index++] = key;
			}
			return maximumGap2(noRepeatNums);
		}
	    public int maximumGap2(int[] nums) {
	        int len = nums.length;
	        if(len<2) return 0;
	        int min=Integer.MAX_VALUE, max=Integer.MIN_VALUE;
	        //第一个循环找出最大、最小值
	        for(int i=0; i<len; i++) {
	        	if(nums[i]<min) {
	        		min = nums[i];
	        	}
	        	if(nums[i]>max) {
	        		max = nums[i];
	        	}
	        }
	        int gap = max - min ;
	        if(gap==1) return 1;
	        int bucketSize = (gap+1)/len;	//此处很奥妙,gap不加1会出现越界问题,最大的数会放到最后一个桶的后面的一个不存在的桶里面
	        int bucketLen = (int) Math.ceil((gap+1)*1.0/bucketSize);

	        List[] bucket = new List[bucketLen];
	        //第二个循环,把所有数据放入合适的桶中
	        //数组中元素个数是len,桶的个数是len或者len+1,这样能保证最小的数字和最大的数字分别在第一个桶和最后一个桶
	        //这样最大的桶间距就是所求的结果
	        for(int i=0; i<len; i++) {
	        	int index = (nums[i]-min)/bucketSize;
	        	
	        	if(bucket[index]==null) {
	        		ArrayList<Integer> list = new ArrayList<Integer>();
	        		list.add(nums[i]);//list.get(0)放最小数
	        		list.add(nums[i]);//list.get(1)放最大数
	        		list.add(nums[i]);
	        		bucket[index] = list;
	        	}else {
	        		ArrayList<Integer> list = (ArrayList<Integer>)bucket[index];
	        		if(nums[i]<list.get(0)) {
	        			list.set(0, nums[i]);
	        		} else if(nums[i]>list.get(1)) {
	        			list.set(1, nums[i]);
	        		}
	        		list.add(nums[i]);
	        	}
	        }
	        
	        //第三个循环,找出最大桶间距,注意:第一个桶和最后一个桶分别有最小数和最大数
	        int result = 0;
	        int leftMax = Integer.MIN_VALUE;
	        int rightMin = Integer.MAX_VALUE;
	        for(int i=1; i<bucket.length; i++) {//前面的桶取最小数,当前桶取最大数
	        	//前一个桶不为空,并且大左值没有求出来
	        	if(bucket[i-1]!=null&&leftMax==Integer.MIN_VALUE) {
					ArrayList<Integer> list = (ArrayList<Integer>)bucket[i-1];
					int tmp = list.get(1);
					if(tmp>leftMax) {
						leftMax = tmp;
					}
	        	}
	        	//当前桶不为空
	        	if(bucket[i]!=null) {
	        		ArrayList<Integer> list = (ArrayList<Integer>)bucket[i];
					int tmp = list.get(0);
					if(tmp<rightMin) {
						rightMin = tmp;
					}
	        	}
	        	
				if(leftMax!=Integer.MIN_VALUE&&rightMin!=Integer.MAX_VALUE) {
					int tmp = rightMin- leftMax ;
					if(tmp>result) {
						result = tmp;
						if(tmp==7) {
							System.out.println("test");
						}
					}
					//重置max,min
					leftMax = Integer.MIN_VALUE;
					rightMin = Integer.MAX_VALUE;
				}
	        }

	        
	        return result;
	    }
	}

	public static void main(String[] args) {
		subject164 subject = new subject164();
		Solution s = subject.new Solution();
		
		int[] nums = { 0,6,3,16,7,10,9,11,20,18 };
		//int[] nums = {1,1,2,1  };
		//int[] nums = {92,30851,24320,20449,7333,29396,10949,17319,9810,26639,20622,3359,14259,4050,21966,22269,24440,20895,2386,25837,628,12174,4901,29663,2720,18750,15281,29858,1891,2833,11814,21685,8976,23961,14880,18778,4529,26957,22660,20715,23811,17025,30634,24177,12737,4501,21186,25459,4645,2924,22640,11276,4525,19999,25786,16704,32283,30195,21028,17808,6591,32393,9753,32716,19192,17493,23693,2089,25849,14929,5857,19348,28105,10227,12807,22853,1421,860,2022,11926,21258,15314,24576,29974,6502,2160,21330,26329,23342,3868,10107,19731,11934,30650,25889,19685,10012,16287,11665,30327,30725,24905,5029,19015,13484,9293,31723,10433,20896,10640,18435,24591,19246,1978,20809,19506,5415,3048,30389,15698,14308,29346,16895,6226,16006,11532,26630,26024,23170,1632,10354,17004,24670,15771,20632,26542,437,26487,26015,15373,26753,11418,14817,9093,6042,14349,29076,393,13433,27119,15018,8530,7746,8811,15349,30838,30210,14567,32655,30652,31796,29566,23673,24111,26507,4785,9090,17009,6379,17753,4971,18002,20664,6368,22600,10401,18772,14769,6697,10563,23267,6125,24314,29569,3154,17504,17320,678,13719,6579,20614,13514,5946,1507,27886,32745,2836,2034,13867,32056,12887,13788,15766,16056,17614,24268,29184,8971,25958,7568,14416,7047,8174,28490,30573,6281,29723,8809,7007,4107,4559,12760,21425,21113,10906,24693,4377,8641,31874,10437,1627,16042,31231,21734,12394,24678,13130,21189,10704,19050,25815,6289,19793,29821,20256,11631,27595,30991,15269,10863,6497,15821,21297,18366,21976,2674,10590,18974,5185,480,8539,25748,26073,12655,4077,25184,19501,10885,16052,11570,30338,23143,13488,923,28275,5198,26628,29634,30684,446,15609,28248,10231,27923,30277,1486,30661,6749,31374,11717,21936,8813,4906,3782,31342,1072,2089,16947,1320,24636,15765,2685,8924,4777,13816,23448,17664,7970,7711,18348,11112,9019,17950,9230,17769,17157,11156,31342,11839,17377,31024,6738,18604,18833,8052,24259,15842,27029,27321,31813,25507,2228,14964,27405,19879,14041,15799,16751,3646,32032,22779,4758,27190,21041,6428,9591,1023,10445,22437,6151,16909,19622,29774,17068,29822,372,18371,28658,32253,6213,13223,15488,998,28436,29657,13130,27050,3742,5366,31240,7030,23153,13343,8678,27663,1862,27644,28797,2561,19344,4864,13570,20472,32341,12015,32189,29806,6205,16798,16829,23686,19177,21243,21195,5688,8837,23628,11164,15791,26017,30908,28235,20975,10044,32531,9990,15547,16162,26821,9991,4534,7289,10798,3013,18632,9878,24604,18028,30659,8213,30350,14219,20295,16424,11451,13069,24291,30255,6742,107,25724,2953,6673,11040,10995,6058,15712,14172,15362,31342,11647,3836,26983,20653,7606,15034,28997,5904,13020,15265,16839,28451,1050,6341,8198,15019,6385,30000,13869,313,2174,16927,19675,21503,7677,24943,13256,9187,9869,19538,7596,15826,19506,4678,29532,24919,8736,17480,25142,9580,17975,8260,10688,8080,15306,4305,27788,281,25508,21787,2143,7884,13645,25888,14737,5803,7561,26144,3511,2062,9762,17230,27008,4597,19175,16076,9693,2973,8181,3798,2149,11089,11573,23358,6903,3971,8998,12056,9889,24091,19677,12982,21952,28175,25418,16855,16745,12084,9660,12827,28168,17492,23463,23994,31559,896,9126,18038,2866,20647,13244,25806,9368,1640,28383,30581,5300,24869,29623,26370,5132,8281,2211,4585,12954,21035,2301,5290,20266,32067,14239,25160,7683,7388,6821,16637,713,8986,17525,32556,16802,30110,11773,29847,19352,6233,1596,9170,10815,31389,6916,4088,20119,6778,16126,6812,18227,29255,20718,32258,8603,25727,18488,14223,31472,6607,27300,30335,974,1388,3934,25302,31606,938,4929,20633,26157,18123,25172,13117,735,1556,14997,25952,17416,8999,3062,6327,20437,14732,6566,584,19334,19601,16529,5849,30230,1876,1834,27560,22046,17182,23144,3932,32503,18418,7182,28476,12574,31590,26160,7327,23005,29106,10227,1699,13864,5383,32660,31778,7366,22306,30124,2530,13233,8480,32178,2316,5310,30100,24513,29152,9600,30935,28571,18086,9834,21407,13551,10984,15669,9171,26839,31454,32385,28574,27813,30506,15039,20163,7647,22726,4686,15920,11144,24890,5348,20949,20641,15122,28720,14518,6128,16015,29118,18239,3328,28317,24602,31704,32361,16901,28472,12730,13649,3300,21523,30209,17971,7772,15253,13058,24288,26249,10423,9694,13763,14518,32233,21080,32360,32209,13748,26851,1856,27421,3742,21247,25758,4391,11854,22982,19718,22267,32752,6850,2727,13719,20955,16130,9766,18336,30321,10349,11933,340,27719,2390,17124,9408,20871,6736,16399,17971,9874,25155,14647,29938,9193,17599,7294,23597,10061,19089,10573,28722,31781,22676,7136,31713,801,18634,12805,8800,32029,6571,27936,10512,32072,10173,13683,7615,18053,9573,17052,11551,6161,17661,27999,15734,11622,18726,20134,8600,30048,28512,20422,30739,17567,26840,4100,2729,1836,21888,17240,16899,13663,30053,28273,419,4096,1086,9208,27,26540,29504,10009,28540,29562,30010,5952,2578,31455,4317,2336,22350,22223,11611,12538,15620,3621,19765,540,12503,4421,27469,26536,7665,22784,11843,31382,21239,27832,26110,22780,3131,5060,1929,653,28212,13845,6945,24160,1068,12314,20620,19956,5945,7650,11692,29040,29038,24961,2899,303,24914,26804,21593,24699,4497,30152,15084,19865,2290,28599,22568,21255,26249,32149,27111,24065,11822,28970,8923,7753,14638,17633,16602,4904,8000,12513,23928,27056,11194,7033,11483,4165,13060,26817,7883,9052,23629,28030,5641,6017,13182,2375,10722,17567,5996,11238,9731,13948,22610,18945,15503,26243,6782,1274,7791,17094,20810,2579,28138,9795,26190,27862,16245,9830,24788,180,7372,22992,8588,30188,15937,31831,1666,15790,28244,5198,2892,31104,19333,32006,14728,31202,23654,31380,32134,4141,10740,15061,13121,14273,21543,26544,32660,23135,21704,11931,18858,13268,25731,24929,26807,6360,13885,5154,23013,9525,31912,23707,4754,5420,28180,5799,17080,19988,14984,20998,7084,23108,10257,19806,28428,23603,18778,8831,14834,15582,637,2027,28782,6506,20505,19350,7476,13323,1189,27370,10641,27684,28675,27662,24996,432,9560,23656,2250,10208,21276,6241,4698,11013,24941,16488,21139,11697,19113,32569,15314,16665,25147,1375,31752,23742,32181,24055,3692,31053,13344,184,5485,21187,10127,17712,4331,5588,3323,6992,17574,31886,26186,11563,25335,7738,8881,19963,20414,30339,6460,23141,3995,26586,4523,28158,14177,15640,20352,4621,28615,28261,21334,18835,24929,11609,18036,7816,7375,31842,17570,5224,21301,21862,30780,9198,29419,9129,15492,9247,31861,5360,14908,17547,9141,1511,12917,31952,4447,3520,27554,5471,22702,27933,29936,11651,30037,25648,13274,25247,26041,13344,28663,31927,13661,20399,20759,17457,2973,32539,911,25821,4768,31553,30417,564,19080,17416,27200,24797,7403,13821,15426,18806,17543,9019,12182,2192,23857,29582,6888,12283,12303,4056,13986,32069,4103,7347,32006};
		int result = s.maximumGap(nums);
		System.out.println(result);

	}
}

在这里插入图片描述
以下代码是按照《漫画》算法中的思路写出来的,总体上来讲条理性更强一点,代码如下:

public class Solution {

    public int maximumGap(int[] array){
    	if(array.length < 2) return 0;
        //1.得到数列的最大值和最小值
        int max = array[0];
        int min = array[0];
        for(int i=1; i<array.length; i++) {
            if(array[i] > max) {
                max = array[i];
            }
            if(array[i] < min) {
                min = array[i];
            }
        }
        int d = max - min;
        //如果maxmin相等,说明数组所有元素都相等,返回0
        if(d == 0){
            return 0;
        }

        //2.初始化桶
        int bucketNum = array.length+1;
        Bucket[] buckets = new Bucket[bucketNum];
        for(int i = 0; i < bucketNum; i++){
            buckets[i] = new Bucket();
        }
        int index = 0;
        int bucketSize = (int)Math.ceil(d*1.0/ (bucketNum-1));
        //3.遍历原始数组,确定每个桶的最大最小值
        for(int i = 0; i < array.length; i++){
            //确定数组元素所归属的桶下标
            index = ((array[i] - min)  / bucketSize);
            System.out.println(array[i]+min+":"+":"+index+":"+":"+bucketSize+":"+d);
            if(buckets[index].min==null || buckets[index].min>array[i]){
                buckets[index].min = array[i];
            }
            if(buckets[index].max==null || buckets[index].max<array[i]){
                buckets[index].max = array[i];
            }
        }

        //4.遍历桶,找到最大差值
        int leftMax = buckets[0].max;
        int maxDistance = 0;
        for (int i=1; i<buckets.length; i++) {
            if (buckets[i].min == null) {
                continue;
            }
            if (buckets[i].min - leftMax > maxDistance) {
                maxDistance = buckets[i].min - leftMax;
            }
            leftMax = buckets[i].max;
        }

        return maxDistance;
    }

    /**
     **/
    private static class Bucket {
        Integer min;
        Integer max;
    }

    public static void main(String[] args) {
        int[] array = new int[] {601408776,63967816,431363697,242509930,15970592,60284088,228037800,147629558,220782926,55455864,456541040,106650540,17290078,52153098,103139530,294196042,16568100,426864152,61916064,657788565,166159446,1741650,101791800,28206276,6223796,524849590,125389882,84399672,153834912,164568204,1866165,283209696,560993994,16266096,219635658,9188983,485969304,782013650,120332636,44659356,444517408,36369045,47370708,18542592,98802990,137690000,124889895,56062800,265421676,309417680,4634176,801661539,510541206,258227892,398938089,47255754,152260962,409663140,102847688,45756553,377936600,269498,375738702,263761134,53797945,329493948,224442208,508336845,189507850,40944620,127879560,119629476,186894520,62409156,693721503,4289916,523899936,28955240,266488028,20356650,40769391,483694272,97988044,84102,67246047,310688630,41288643,58965588,42881432,152159462,94786355,174917835,119224652,525034376,261516,274800528,62643819,23613832,8397240,797832131,855155367,337066320,26341480,61932200,20661075,515542796,390337500,522552030,43538516,150800550,116747540,152989123,488640056,700610304,233604,344277340,21439176,9397864,16365822,73027584,453041413,197374275,157735188,15273822,187081152,379611084,865005504,223099767,80478651,377729400,186738219,34738263,16634072,112791343,99631856,119364960,477106486,583953920,624509809,188442472,294181256,213023715,146645884,149530380,497592753,132170327,72770643,126683010,405141255,590214306,26670714,95582385,162080790,231120099,8946432,204967980,592849110,54120698,375915096,602145859,5346440,226337825,425156369,653591624,578483360,572410800,32290700,381384563,149939976,183225375,155695620,38307636,457513760,97085778,75200576,8068176,221650296,556889418,252495726,895020231,19932465,156334887,191383314,348432526,368701264,14315598,148936587,279419435,237325542,252587218,322929504,26331343,355297676,600420786,652017765,51673622,159015675};
    	//int[] array = {1,1,1,1,5,5,5,5};
        System.out.println(new Solution().maximumGap(array));
    }

}
发布了80 篇原创文章 · 获赞 133 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/chekongfu/article/details/90897894