无序数组排序后,求相邻两数之间的最大差值,代码过程详解

题目:

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

示例:

例如:3  1  6  2  7   排序之后  :  1  2  3  6  7   则相邻最大差值为3(6-3=3)

解法:

1.循环数组,找到最小值和最大值。

2.若有N个数,就创建N+1个桶来装数,分别为   0号桶,1号桶,2号桶......N号桶 。

3.定义三个大小为N+1的数组。

4.循环原数组, 确定每个数被装入哪个桶。如何确定?-->which = (num-min)*N/(max-min),每个桶内只能存放进入该桶的最大值和最小值。

5.循环求后一个桶的最小值减去前一个桶的最大值,即得到最大差值。若是空桶,则跳过。

注释:

1.一共N个数,N+1个桶,且全局最小值放在第一个桶,全局最大值放在最后一个桶,那么中间必有桶是空桶。

2.空桶的意义:排除最大差值的两个相邻的数在同一个桶中。

空桶左边的桶内差值最大是9,空桶两边最小差值为11(30-19=11),但是并不是空桶两边的差值就是最大,看图中最右边两个桶,他们的差值是19(49-30=19)。因此,空桶的意义在于排除最大差值是在同一个桶中出现。

 

代码实现 (Java):

public class MaxGap {

	public static int maxGap(int[] nums) {
		if (nums == null || nums.length < 2) {
			return 0;
		}
		int len = nums.length;
		int min = Integer.MAX_VALUE;
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < len; i++) {
			min = Math.min(min, nums[i]);
			max = Math.max(max, nums[i]);
		}
		if (min == max) {
			return 0;
		}
		boolean[] hasNum = new boolean[len + 1];
		int[] maxs = new int[len + 1];
		int[] mins = new int[len + 1];
		int bid = 0;
		for (int i = 0; i < len; i++) {
			bid = bucket(nums[i], len, min, max);
			mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i];
			maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i];
			hasNum[bid] = true;
		}
		int res = 0;
		int lastMax = maxs[0];
		int i = 1;
		for (; i <= len; i++) {
			if (hasNum[i]) {
				res = Math.max(res, mins[i] - lastMax);
				lastMax = maxs[i];
			}
		}
		return res;
	}

	public static int bucket(long num, long len, long min, long max) {
		return (int) ((num - min) * len / (max - min));
	}
}

 

 代码实现(Python):

# 空桶的意义是说明:最大差值不可能是来自同一个桶内的两个数。
import sys
def max_difference(arr):
    max_num = -sys.maxsize  # 最大值取系统最小值
    min_num = sys.maxsize  # 最小值取系统最大值
    for i in arr:  # 循环arr数组中的每一个数
         max_num = max_num if i < max_num else i
         min_num = min_num if i > min_num else i
    bool_bucket = ["false"] * (len(arr)+1)
    min_bucket = [None] * (len(arr)+1)
    max_bucket = [None] * (len(arr)+1)
    for i in arr:
        which = which_bucket(i, min_num, max_num, len(arr))
        if bool_bucket[which] == "false":
            min_bucket[which] = i
            max_bucket[which] = i
            bool_bucket[which] = "true"
        else:
            min_bucket[which] = min(min_bucket[which], i)
            max_bucket[which] = max(min_bucket[which], i)

    pre_max = max_bucket[0]
    ret = 0
    for i in range(1, len(arr)+1):  # 从第二个桶开始
        if bool_bucket[i] == "true":  # 假设空桶就跳过,利用空桶下一个桶中最小值减去空桶上一个桶的最大值求差值。
           ret = max(ret, (min_bucket[i] - pre_max))
           pre_max = max_bucket[i]
    return ret

# 求数组中的数分配的桶号
def which_bucket(num, min_num, max_num, len):
    return int((num-min_num) * len / (max_num - min_num))


arr = [4, 3, 2, 1, 7]
print(max_difference(arr))
# 3  --> 7-4=3

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值