排序相关—— 相邻两数的最大差值( Maximum Gap-LeetCode)



题目链接:https://leetcode.com/problems/maximum-gap/#/description

参考答案:http://www.programcreek.com/2014/03/leetcode-maximum-gap-java/


给定一个整型数组arr,返回如果排序之后,相邻两数的最大差值。例如:某数组排序之后为 1 2 3 4 7 8 9,最大差值来自于4和7,所以返回3.

最优解时间复杂度为O(N),额外空间复杂度为O(N).

这道题的思想是桶排序,但不是真正的桶排序。

思路:

1.找出数组的最大值和最小值

2.把最大值和最小值上的数[min,max)等量地分成n个区间,n为数组个数;每个区间分别对应一个桶,每个数根据各自的区间选择进入的桶,把最大值单独放在n+1号桶中。

3.因为桶的数量有n+1个,而数组的个数只有n个,因此必然存在空桶。同一个桶中数的差值肯定不会大于桶区间,而来自空桶两侧的差值必然大于桶区间。所以不用考虑一个桶中的相邻数,只需要考虑来自两个桶的相邻数的差值,即后一个桶的最小值和前一个桶的最大值。

4.接下来只需要考虑每个桶的最小值和上一个桶中的最大值自己的差值,并且记录他们的最大差值,即为结果。


public class FindMaxDivision {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] nums={7,9,3,4,2,1,8};
		System.out.println(findMaxDivision(nums));
	}
	
	public static int findMaxDivision(int[] nums){
		if(nums==null || nums.length<2)
			return 0;
		
		//找出数组的最大值和最小值
		int max=nums[0];
		int min=nums[0];
		for(int i=1;i<nums.length;i++){
			if(nums[i]<min){
				min=nums[i];
			}
			if(nums[i]>max){
				max=nums[i];
			}
		}
		if(max==min)
			return 0;
		int[] minA=new int[nums.length+1]; //存放每个桶中的最小值,最后一个桶刚好用来放最大值
		int[] maxA=new int[nums.length+1]; //存放每个桶中的最大值
		for (int i=0; i<nums.length+1; ++i) {
			minA[i] = -1;
			maxA[i] = -1;
        }
		double interval=(double)nums.length/(max-min);
		for(int i=0;i<nums.length;i++){   //注意i的范围,不是nums.length+1,会越界
			int tag=(int)((nums[i]-min)*interval);
			if(minA[tag]==-1){
				minA[tag]=nums[i];
				maxA[tag]=nums[i];
			}else{
				minA[tag]=Math.min(minA[tag],nums[i]);
				maxA[tag]=Math.max(maxA[tag],nums[i]);
			}
		}
		
		///找出第一个空桶的前一个桶的最大值和最后一个空桶的后一个桶的最小值
		
		int result=0;
		int prev=maxA[0];
		for(int i=1;i<nums.length+1;i++){
			if(minA[i]!=-1){
				result=Math.max(result,minA[i]-prev);
				prev=maxA[i];
			}
		}
		return result;
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值