漫画算法-学习笔记(22)

漫画算法-小灰的算法之旅(22)

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

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

可能题目有点绕,让我们看看下图的例子:

方法一(排序数组+遍历求解)
思路

使用任意一种时间复炸度为O(nlogn)的排序算法(如快速排序)给原数组排序,然后遍历排好序的数组,并对每两个相邻元素求差,最终得到最大差值。

时间复杂度

该解法的时间复杂度是O(nlogn),在不改变原数组的情况下,空间复杂度是O(n).

代码实现


// go 实现排序+遍历
方法二(计数排序思想)
思路

利用计数排序的思想,先求出原数组的最大值max与最小值min的区间长度k(k=max-min+1);以及偏移量d=min.

创建一个长度为k的新数组Array

遍历原数组,每遍历一个元素,就把新数组Array对应下标的值+1。例如原数组元素的值为n,则将Array[n-min]的值加1。遍历结束后,Array的一部分元素值变成了1或者更高的数值,一部分元素值任为零。

遍历新数组Array,统计出Array中最大连续出现0值的次数+1,即为相邻元素最大差值。

例如给定一个无序数组{2,6,3,4,5,10,9},处理过程如下图

第一步,确定k(数组长度)和d(偏移量)

第二步,创建数组

第三步,遍历原数组,对号入座

第四步,判断0值最多连续出现的次数,计算出最大相邻差。

代码实现
// go 代码实现
方法三(桶排序思想)
思路

利用桶排序的思想,根据原数组的长度n,创建出n个桶,每一个桶代表一个区间范围。其中第1个桶从原数组的最小值min开始。区间跨度是(max-min)/(n-1).

遍历原数组,把原数组每一个元素插入到对应的桶中,记录每一个桶的最大和最小值。

遍历所有的桶,统计出每一个桶的最大值,和这个桶右侧非空桶的最小值的差,数值最大的差即为原数组排序后的相邻最大差值。

例如给出一个无序数组{2,6,3,4,5,10,9},处理过程如下图

第一步,根据原数组,创建桶,确定每个桶的区间范围

第二步,遍历原数组,确定每个桶内的最大值和最小值

第三步,遍历所有的桶,找出最大相邻差

时间复杂度

这个方法不许要像标准桶排序那样给每一个桶内部进行排序,只需要记录桶内的最大和最小值即可,所以时间复杂度稳定在O(n)

代码实现
public static int getMaxSortedDistance(int[] array){
  // 1. 得到数列的最大值和最小值
  int max =array[0];
  int min =array[0];
  for(int i=1;i<array.length;i++){
    if(array[i]>max){
      max=array[i];
    }
    if(array[i]<min){
      min=array[i];
    }
  }
  int d =max-min;
  //如果max 和min 相等,说明数组所有元素都相等,返回0
  if(d==0){
    return 0:
  }
  // 2 初始化桶
  int bucketNum=array.length;
  Bucket[] buckets=new Bucket[bucketNum];
  for(int i=0;i<bucketNum;i++){
    buckets[i]=new Bucket();
  }
  //3.遍历原始数组,确定每个桶的最大最小值
  for(int i=0;i<array.length;i++){
    //确定数组元素所归属的桶下标
    int index=((array[i]-min)*(bucketNum-1)/d);
    if(buckets[index].min==null || buckets[index].min>array[i]){
      buckets[index].min=array[i];
    }
    if(buckets[index].max==null || buckets[index].max<array[i]){
      buckets[index].max=array[i];
    }
  }
  //4. 遍历桶,找到最大差值
  int leftMax=buckets[0].max;
  int maxDistance=0;
  for(int i=1;i<buckets.length;i++){
    if(buckets[i].min==null){
      continue;
    }
    if(buckets[i].min -leftMax>maxDistance){
      maxDistance=buckets[i].min-leftMax;
    }
    leftMax=buckets[i].max;
  }
  return maxDistance;
}

/**
* 桶
*/
private static class Bucket{
  Integer min;
  Integer max;
}

public static void main(String[] args){
  int[] array=new int[]{2,6,3,4,5,10,9};
  System.out.println(getMaxSortedDistance(array));
}

代码的前几步都比较直观,唯独第4步稍微有些不好理解,使用临时变量leftMax,在每一轮迭代时存储当前左侧桶的最大值。而两个桶之间的差值,则是buckets[i].min-leftMax.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值