无需数组排序后的最大相邻差

打印 上一主题 下一主题

主题 888|帖子 888|积分 2664

题目

有一个无序整型数组,如何求出该数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。
思绪

解法1:使用任意一种时间复杂度为O(nlogn)的排序算法(如快速排序),给原数组排序,然后遍历排序号的数组,并对每队相邻元素求差,最终得到最大差值。该解法的时间复杂度是O(nlogn),在不改变原数组的情况下,空间复杂度是O(n)。
解法2:

  • 1.使用计数排序的思想,先求出原数组的最大值max和最小值min的区间长度k(k=max-min+1),以及偏移量d=min。
  • 2.创建一个长度为k的新数组Array。
  • 3.遍历原数组,每遍历一个元素,就把新数组Array对应下标的值+1。Array[n-min]的值+1。遍历结束后,Array的一部分元素值变成了1或更高的数值,一部分元素值仍然是0。
  • 4.遍历新数组Array,统计出Array中最大的一连出现的0值得次数+1,即为相邻元素最大差值。
  • 5.这条思绪有限制,由于计数排序,只实用于正整数的排序。
解法3:

  • 1.使用桶排序的思想,根据原数组的长度n,创建出n+1个桶,注意是n+1桶,每一个桶代表一个区间范围。其中第1个桶从原数组的最小值min开始,区间跨度是(max -min)/n。
  • 2.遍历原数组,把原数组每一个元素插入到对应的桶中,记录每一个桶的最大值和最小值。
  • 3.遍历所有的桶,,统计出每一个桶的最大值,和该桶右侧非空桶的最小值的差,数值最大的差即为原数组排序后的相邻最大差值。
注意,这里少了一个说明,为什么排序后最大的两个相邻元素的差,一定会是每一个桶的最大值,和该桶右侧非空桶的最小值的差,的最大值。
先从n个数,分到n+1个桶里,开始说明。第n+1个桶的区间,是[max,max],第1个桶的区间,是[min,min+d],d为前n个桶区间的差值。n个数,最小值,一定落在第一个桶里,最大值,一定在n+1个桶里,还有n-2个数,n-2个数,分散到n+1-2=n-1个桶里,则在这n-1个桶中,一定会由空桶,则相邻两个数的最大值的差值,一定出现在,最大一连空桶个数的左边第一个桶的最大值,和右边第一个桶的最小值。也可以说是每一个桶的最大值,和该桶右侧非空桶的最小值的差,数值最大的差。由于桶内,两个元素的最大差值,一定是小于区间差值d的。
将n+1桶,和并到第n个桶内,此时就是n桶就是[]的。此时n个数,分散到n个桶里,没有空桶最分散的情况,也就是每个桶里一个元素,两个相邻元素的最大差值也是,每一个桶的最大值,和该桶右侧非空桶的最小值的差,数值最大的差,假如出现空桶,和上面n+1个桶的情况就划一了。
所以,统计出每一个桶的最大值,和该桶右侧非空桶的最小值的差,数值最大的差即为原数组排序后的相邻最大差值。
代码
  1. @SuppressWarnings("all")
  2. public class MaxGroup {
  3.     public static int getMaxGroup(int[] array) {
  4.         int arrayLen = array.length;
  5.         if (arrayLen < 2)
  6.             return 0;
  7.         //1.得到数列的最大值和最小值
  8.         int max = array[0];
  9.         int min = array[0];
  10.         for (int i = 1; i < arrayLen; i++) {
  11.             if (max < array[i])
  12.                 max = array[i];
  13.             if (min > array[i])
  14.                 min = array[i];
  15.         }
  16.         int d = max - min;
  17.         if (d == 0)
  18.             return 0;
  19.         //2.初始化桶
  20.         int bucketNum = arrayLen;
  21.         Bucket[] buckets = new Bucket[bucketNum];
  22.         for (int i = 0; i < bucketNum; i++)
  23.             buckets[i] = new Bucket();
  24.         //3.遍历原始数组,确定每个桶的最大最小值
  25.         for (int i = 0; i < arrayLen; i++) {
  26.             int index = ((array[i] - min) / d * (bucketNum - 1));//求出当前元素,在整体区间的比值,再放大(len - 1)倍就是桶(所在区间)的索引 index + 1是桶的个数
  27.             if (buckets[index].getMin() == null || buckets[index].getMin() > array[i])
  28.                 buckets[index].setMin(array[i]);
  29.             if (buckets[index].getMax() == null || buckets[index].getMax() < array[i])
  30.                 buckets[index].setMax(array[i]);
  31.         }
  32.         //4.遍历桶,找到最大差值
  33.         int leftMax = buckets[0].getMax();
  34.         int maxGroup = 0;
  35.         for (int i = 1; i < bucketNum; i++) {
  36.             if (buckets[i].getMin() == null)
  37.                 continue;//空桶跳过,如果桶非空,则该桶的min和max值,一定不为空
  38.             int differNum = buckets[i].getMin() - leftMax;
  39.             if (differNum > maxGroup)
  40.                 maxGroup = differNum;
  41.             leftMax = buckets[i].getMax();//
  42.         }
  43.         return maxGroup;
  44.     }
  45.     private static class Bucket {
  46.         Integer min;
  47.         Integer max;
  48.         public Integer getMin() {
  49.             return min;
  50.         }
  51.         public void setMin(int min) {
  52.             this.min = min;
  53.         }
  54.         public Integer getMax() {
  55.             return max;
  56.         }
  57.         public void setMax(int max) {
  58.             this.max = max;
  59.         }
  60.     }
  61.     public static void main(String[] args) {
  62.         int[] array = new int[]{2, 5, 3, 4, 5, 10, 8};
  63.         System.out.println(getMaxGroup(array));
  64.     }
  65. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表