给定一个无序数组,求这组数在排序后相邻数间差的最大值

题目来源:https://oj.leetcode.com/problems/maximum-gap/

题目大意:RT

这个题最差的方式是排序,当然时间复杂度是nlogn。

是否有n的方法呢?

假设这组数的最大值为max,最小值为min,对于这样的数据,最差情况就是所有的值的差都相同,那么相邻的最大值为(max-min)/(n-1)。而且修改任何一个数字都将造成结果的增加。

通过这种方法,把min~max分割成N-1个区间(前闭后开),然后将每个数放到对应的区间里。
这样,相邻数字差的最大值其实和区间内的数据无关了(因为区间内无论计算,其结果都将<(max-min)/(n-1))。这样分组后,最终的结果应当就是前一个区间的最大值与后一个区间的最小值的差,当然会出现空的区间,做个标记即可。

时间和空间复杂度都为O(N)

/**
 * Created by jpbirdy on 15-1-16.
 */

package jpbirdy.leetcode;

/**
 * 给定一个无序数组,找到数组中排序后相邻差最大的值
 *
 * @author jialou.jp
 * @project JavaAlgorithms
 * @class MaxGap
 * @date 15-1-16 17:01
 */
public class MaxGap
{
    public int maximumGap(int[] num)
    {
        int maxGap = 0;

        // edge case
        if (num.length < 2)
        {
            return maxGap;
        }

        // get maximum and minimum
        int min = num[0];
        int max = num[0];
        for (int i = 0; i < num.length; i++)
        {
            if (num[i] < min)
                min = num[i];
            if (num[i] > max)
                max = num[i];
        }

        // divide into identical gaps
        Gap[] gaps = new Gap[num.length - 1];
        boolean[] Engaged = new boolean[num.length - 1];
        double gap = (double) (max - min) / (double) (num.length - 1);
        for (int i = 0; i < gaps.length; i++)
            Engaged[Math.min((int) Math.floor((double) (num[i] - min) / gap), gaps.length - 1)] = true;

        // assign maximum and minimum for each gap
        for (int i = 0; i < gaps.length; i++)
            gaps[i] = new Gap();
        for (int i = 0; i < num.length; i++)
        {
            int index = (int) Math.floor((double) (num[i] - min) / gap);
            index = Math.min(index, gaps.length - 1);

            // lower bound
            if (gaps[index].low == -1)
                gaps[index].low = num[i];
            else
                gaps[index].low = Math.min(gaps[index].low, num[i]);

            // upper bound
            if (gaps[index].high == -1)
                gaps[index].high = num[i];
            else
                gaps[index].high = Math.max(gaps[index].high, num[i]);
        }

        // find maximum gap
        for (int i = 0; i < gaps.length; i++)
        {
            if (Engaged[i])
            {
                // check its inner gap
                maxGap = Math.max(gaps[i].high - gaps[i].low, maxGap);

                // lower all the way
                int j = i;
                while (--j >= 0)
                {
                    if (Engaged[j])
                        break;
                }
                if (j >= 0)
                    maxGap = Math.max(gaps[i].low - gaps[j].high, maxGap);

                // upper all the way
                j = i;
                while (++j < num.length - 2)
                {
                    if (Engaged[j])
                        break;
                }
                if (j < gaps.length)
                    maxGap = Math.max(gaps[j].low - gaps[i].high, maxGap);
            }
        }

        return maxGap;
    }

    class Gap
    {
        int low;
        int high;
        boolean hasItem;

        Gap()
        {
            low = -1;
            high = -1;
        }

        Gap(int x, int y)
        {
            low = x;
            high = y;
        }
    }

    public static void main(String[] args)
    {
        int[] num = {1, 2, 3, 5, 7, 9};
        System.out.println((new MaxGap()).maximumGap(num));
    }

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值