相邻最大差值

题目描述

请设计一个复杂度为O(n)的算法,计算一个未排序数组中排序后相邻元素的最大差值。
给定一个整数数组A和数组的大小n,请返回最大差值。保证数组元素个数大于等于2小于等于500。
测试样例:
[9,3,1,10],4
返回:6

通过的代码

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class Main {

    public static void main(String args[])
    {
        int asdf[]=new int[]{96,614,146,429,487,250,536,392,178,26,569,178,595,129,363,550,26,492,561,435,113,492,44,213,478,590,593,488,72,231,73,190,40,62,448,563,1,582,453,33,538,407,57,214,137,193,253,323,167,511,278,148,581,557,551,126,167,50,438,139,345,203,292,288,233,360,343,308,586,519,495,369,159,126,46,183,482,50,214,264,161,145,504,527,52,578,489,104,269,253,349,464,318,458,96,349,46,563,478,1,395,262,285,46,184,115,146,171,452,223,518,414,33,246,70,286,348,582,338,72,191,58,590,298,538,75,283,459,551,2,41,86,354,58,178,411,321,137,37,41,553,303,380,96,198,125,222,544,97,533,437,610,304,276,98,196,170,240,98,413,328,109,70,270,37,398,377,309,367,86,123,401,480,211,48,506,257,125,137,201,194,188,170,300,49,148,493,439,575,93,588,130,403,220,118,578,419,70,519,558,544,84,594,51,240,68,304,282,27,447,149,486,602,519,261,264,179,362,2,495,564,259,431,162,343,165,86,346,408,559,293,274};

        System.out.println(findMaxDivision(asdf, asdf.length));
        Arrays.sort(asdf);
        System.out.println(Arrays.toString(asdf));
    }


    public static int findMaxDivision(int[] A, int n)
    {
        int max=Integer.MIN_VALUE;
        int min=Integer.MAX_VALUE;
        for(int i=0;i<n;i++)
        {
            if(max<A[i])
            {
                max=A[i];
            }
            if(min>A[i])
            {
                min=A[i];
            }
        }


        int span=(max-min);

        int maxArray[]=new int[n+1];
        Arrays.fill(maxArray, Integer.MIN_VALUE);
        int minArray[]=new int[n+1];
        Arrays.fill(minArray, Integer.MAX_VALUE);
        for(int i=0;i<n;i++)
        {
            int index=(A[i]-min)*n/span;
            if(maxArray[index]<A[i])
            {
                maxArray[index]=A[i];
            }
            if(minArray[index]>A[i])
            {
                minArray[index]=A[i];
            }

        }


        int i=1;
        int j=0;
        int result=0;
        while(i<A.length+1)
        {
            while(i<A.length+1&&minArray[i]==Integer.MAX_VALUE)
            {
                i++;
            }
            if(i>=A.length+1)
            {
                break;
            }
            while(j<i&&maxArray[j]==Integer.MIN_VALUE)
            {
                j++;
            }
            if(j>=i)
            {
                i++;
                continue;
            }
            if(result<minArray[i]-maxArray[j])
            {
                result=minArray[i]-maxArray[j];

            }
            i++;
            j++;
        }


        return result;
    }

}

下面是别人给的思路
关键在于:距离平均值为(max-min)/n-1, 则距离最大的数必然大于这个值 这句话

假设有4个数,最小为0.2, 最大为0.8.
那么这四个数的平均距离为(0.8-0.2)/3 = 0.2
则必然存在两个数的差大于等于0.2,即距离最大的两个数必然不会小于0.2.

分成三个桶,分别是0.2~0.4, 0.4~0.6, 0.6~0.8.
那么距离最大的两个数必然不在同一个桶内.
依次比较上一个桶的最大值与下一个桶的最小值的差值,找最大的即可.

这个问题我碰见了一个奇妙的事情。一开始我我程序写的求一个数的索引的方式是这样的

int span=(max-min)/(n-1);//这一行求出每个桶的大小

        int maxArray[]=new int[n+1];
        Arrays.fill(maxArray, Integer.MIN_VALUE);
        int minArray[]=new int[n+1];
        Arrays.fill(minArray, Integer.MAX_VALUE);
        for(int i=0;i<n;i++)
        {
            int index=(A[i]-min)/span; //这个可以求出桶的索引
            if(maxArray[index]<A[i])
            {
                maxArray[index]=A[i];

其实个代码看似没有问题可是问起缺非常非常大。
考虑这样的一个测试用例
最大值是614,最小值是1.。数组大小为232.
这样我求出的span是(614-1)/232=2.63
可是因为是int所以变成桶大小是2.因为我桶的总数最多是232个桶。可是对于614这个数(614-1)/2=306。远远超出我最大的桶的大小

这个就是int运算带来的问题。
这个题有两个解决办法。span换成double。可是这样会耽误运算。因为桶也要换成double。。double运算比较复杂

第二个方法是把桶大小运算变成取上整数为3.可是桶大小是3的时候给每个数计算桶索引的时候也很麻烦。看了别人的代码。有了一个绝妙的方法。

int span=(max-min);//这一行求出每个桶的大小

        int maxArray[]=new int[n+1];
        Arrays.fill(maxArray, Integer.MIN_VALUE);
        int minArray[]=new int[n+1];
        Arrays.fill(minArray, Integer.MAX_VALUE);
        for(int i=0;i<n;i++)
        {
            int index=(A[i]-min)*n/span; //这个可以求出桶的索引
            if(maxArray[index]<A[i])
            {
                maxArray[index]=A[i];

span是数字的总跨度。然后(A[i]-min)/span肯定是小于1的数字。那么乘以n这样的出来的索引一定是小于n的。。十分美妙的解决方法。值得学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值