题目:

Given an unsorted array, find the maximum difference between the successive elements in its sorted form.

Try to solve it in linear time/space.

Return 0 if the array contains less than 2 elements.

You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.

链接: http://leetcode.com/problems/maximum-gap/

题解:

给定未排序数组,求两个相邻元素间的差的最大值。想了一会不确定,于是去看了一眼Discuss的标题,果然是用Radix Sort。其实一开始看到题目里面所有数字都可以被表示为32-bit signed integer时,就应该要想到才对。 估计做法就是用Radix Sort,排序完毕后再扫描一边数组。正好加深一下对Radix Sort的理解和书写。要好好研究一下Key-indexed Counting,LSD,MSD和Bucket Sort。这道题用Bucket Sort的话就是把每个元素放入一个bucket中,然后计算非空bucket间的最大距离,原理都差不多。一刷用了LSD,代码大都参考Sedgewick大神,二刷的话要试一试MSD以及bucket sort。注意的一点是LSD处理最高8位bit时, 0 ~ 127为正, 128 ~ 255为负,所以要特殊处理一下accumulated count数组。做完这题以后就发现上过算法2真好...

LSD Radix Sort, Time Complexity - O(n),  Space Complexity - O(n)

public class Solution {
public int maximumGap(int[] nums) {
if(nums == null || nums.length < 2)
return 0;
lsdSort(nums);
int maxDiff = Integer.MIN_VALUE;
for(int i = 1; i < nums.length; i++)
maxDiff = Math.max(nums[i] - nums[i - 1], maxDiff); //may overflow
return maxDiff;
} private void lsdSort(int[] nums) {
int len = nums.length;
int[] aux = new int[nums.length];
int totalBits = 32;
int bitsPerByte = 8;
int window = totalBits / bitsPerByte;
int R = 1 << bitsPerByte; // R is radix
int mask = R - 1; // for(int d = 0; d < window; d++) { // for each window compared
int[] count = new int[R + 1]; for(int i = 0; i < len; i++) { // count least significant 8 bits of each num in nums
int c = (nums[i] >> (d * bitsPerByte)) & mask; // use mask to get least significant 8 bits
count[c + 1]++;
} for(int i = 0; i < R; i++) // count accumulated position for each nums
count[i + 1] += count[i]; if(d == window - 1) { // for most significant 8 bits, 0 ~ 127 is pos, 128 ~ 255 is neg, so 128 ~ 255 goes first
int shift1 = count[R] - count[R / 2];
int shift2 = count[R / 2];
for(int i = 0; i < R / 2; i++)
count[i] += shift1;
for(int i = R / 2; i < R; i++)
count[i] -= shift2;
} for(int i = 0; i < len; i++) { // move data
int c = (nums[i] >> (d * bitsPerByte)) & mask;
aux[count[c]++] = nums[i];
} for(int i = 0; i < len; i++) // copy back
nums[i] = aux[i];
} }
}

二刷:

依然使用了LSD radix sort,代码大都来自塞神的index counting。

  1. 我们把32位的数字分为4个batch,每个batch有8个digit,使用LSD的话我们是从最低一级的batch开始计算。这里我们要使用一个mask = 255,也就是二进制的11111111来找到每个batch。也要做一个auxiliary array - aux[] 用来保存临时结果
  2. 对于每个batch,我们都要做一次index counting sort,一共四次,从最低8位开始,到最高8位
    1. 每次确定了batch之后我们就可以创建buckets数组。这里buckets数组 count = new int[R + 1] , 这里的 + 1很重要
    2. 我们第一次遍历数组,根据最低8位,统计所有数字出现的频率,然后放入相应的bucket里,这里有个小trick很关键,我们虽然将低8位映射到从[0 - 255]这样的256个bucket里,但写入count数组的时候,我们有意把count[0]留下,把数字的count写到 [1 - 256]的bucket中。这样做的好处,要在后面才能看到,就是从经过aggregation后的count数组,将排序后的数字填入到aux[]数组中时。
    3. 然后,我们对统计好的数字和频率进行aggregation,利用count数组求一个accumulated count。经历过这一步以后,我们的count[i]代表的意思就是,有多少个数字应该被放在 i 之前的buckets里。
    4. 接下来,我们根据aggregation的结果,我们把这些数字填到aux[]里
    5. 最后把aux[]中的数字拷贝回nums中,继续计算下一个batch。 因为LSD的操作是stable的,所以我们进行完全部4个batch以后就会得到最终结果
  3. 这里要注意的一点是,32位数字最高8位digit的这个batch和其他三个不同。在这8位里0 ~ 127为正数,而128 ~ 255为负数。所以在这个batch里,计算完aggregation数组后,我们要做一个很巧妙的shift操作
    1. 先求出shift1 = count[R] - count[R / 2], 也就是在输入的nums[]中有多少个数字为负
    2. 再求出shift2 = count[R / 2], 输入的nums[]中有多少个正数
    3. 对于[0 - 127]的这些数字,他们都应该排在负数前面,所以我们对每一个count[i] 增加 shift1
    4. 对于[128 - 255]的这些数字,他们都应该排在正数后面,所以我们对每一个count[i] 减少 shift2
    5. 之后再根据新的count[]数组,把数字放入aux[]数组中,再拷贝回原数组nums[]里。

Java:

Time Complexity - O(n),  Space Complexity - O(n)

public class Solution {
public int maximumGap(int[] nums) { // LSD
LSDradix(nums);
int maxGap = 0;
for (int i = 1; i < nums.length; i++) maxGap = Math.max(maxGap, nums[i] - nums[i - 1]);
return maxGap;
} private void LSDradix(int[] nums) {
if (nums == null || nums.length == 0) return;
int batchSize = 8;
int batchNum = 32 / batchSize;
int R = 1 << batchSize; // radix, each bucket we consider only [0 - 255] , 256 numbers
int mask = R - 1; // 11111111, each batch 8 digits
int len = nums.length;
int[] aux = new int[len]; for (int d = 0; d < batchNum; d++) {
int[] count = new int[R + 1];
for (int num : nums) {
int idx = (num >> (d * batchSize)) & mask;
count[idx + 1]++; // index counting
}
for (int k = 1; k < count.length; k++) count[k] += count[k - 1]; // aggregation, find out the buckets boundaries
if (d == batchNum - 1) { // for first 8 digits 01111111 is max, 11111111 is min, we shift nums
int shift1 = count[R] - count[R / 2];
int shift2 = count[R / 2];
for (int k = 0; k < R / 2; k++) count[k] += shift1;
for (int k = R / 2; k < R; k++) count[k] -= shift2;
}
for (int num : nums) {
int idx = (num >> (d * batchSize)) & mask;
aux[count[idx]++] = num; // we place each num in each buckets, from the start slot of the bucket
}
for (int k = 0; k < len; k++) nums[k] = aux[k];
}
}
}

Reference:

https://www.cs.princeton.edu/~rs/AlgsDS07/18RadixSort.pdf

https://leetcode.com/discuss/18499/bucket-sort-java-solution-with-explanation-o-time-and-space

https://leetcode.com/discuss/18487/i-solved-it-using-radix-sort

https://leetcode.com/discuss/19951/use-average-gap-to-achieve-o-n-run-time-java-solution

https://leetcode.com/discuss/34289/pigeon-hole-principle

https://leetcode.com/discuss/53636/radix-sort-solution-in-java-with-explanation

164. Maximum Gap的更多相关文章

  1. LeetCode 164. Maximum Gap[翻译]

    164. Maximum Gap 164. 最大间隔 Given an unsorted array, find the maximum difference between the successi ...

  2. leetcode[164] Maximum Gap

    梅西刚梅开二度,我也记一题. 在一个没排序的数组里,找出排序后的相邻数字的最大差值. 要求用线性时间和空间. 如果用nlgn的话,直接排序然后判断就可以了.so easy class Solution ...

  3. 【LeetCode】164. Maximum Gap (2 solutions)

    Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...

  4. 【刷题-LeetCode】164 Maximum Gap

    Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...

  5. ✡ leetcode 164. Maximum Gap 寻找最大相邻数字差 --------- java

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  6. 164. Maximum Gap (Array; sort)

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  7. [LeetCode] 164. Maximum Gap 求最大间距

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  8. Java for LeetCode 164 Maximum Gap

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  9. 164. Maximum Gap *HARD* -- 无序数组找出排序后连续元素的最大间隔

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

随机推荐

  1. mybatis 无法转换为内部表示 解决

    出现这个问题,一般是JavaBean定义的时候数据类型不准造成的. 其中javabean定义的字段的类型并不需要完全和数据库中的字段一样. 在mapper.xml中可能做了转换  比如 CASE WH ...

  2. Jquery中Ajax异步请求中的async参数的作用

    之前不知道这个参数的作用,上网找了前辈的博客,在此收录到自己的博客,希望能帮到更多的朋友: test.html <a href="javascript:void(0)" on ...

  3. JAVA如何解析多层json数据

    1. 使用标准的Json对象,如org.json.JSONObject json = new org.json.JSONObject(yourJsonString);然后通过get(keyString ...

  4. 【html】【9】div布局[div层叠]

    让DIV重叠并按想要顺序重叠需要CSS来实现,即CSS绝对定位进行实现. 重叠样式需要主要CSS样式解释1.z-index 重叠顺序属性2.position:relative和position:abs ...

  5. 三分钟学会CSS3中的FLEXBOX布局

    原文地址,保护版权,请勿转载:http://page.factj.com/blog/p/2574 这篇文章里我们将学习CSS里flexbox布局的几个最重要的概念,通过学习flexbox布局,你会发现 ...

  6. Java编程思想读书笔记--第21章并发

    1.基本的线程机制 定义任务 public class LiftOff implements Runnable{ protected int countDown = 10; private stati ...

  7. 将博客搬迁至CSDN

    CSDN不给我搬家就算了....我自己搬= = http://blog.csdn.net/ourfutr2330

  8. win2008 r2 远程桌面问题

    今天去机房给三台服务器上架,装了2008 R2系统,客户要求从外面通过公网IP能够访问服务器桌面,三台服务器都安装了远程协助的功能,结果有两台能正常访问,另外一台始终连不上,不知道哪个地方设置有问题, ...

  9. Java官方Demo Mark

    Java2D里四个重要的基类:AnimatingSurface:              动画界面基类ControlsSurface:              控制界面基类AnimatingCon ...

  10. .NET高端职位招聘要求

    系统架构师: 1.硕士及以上学历,博士有项目成果者优先: 2.五年以上工作经验,三年以上互联网经验,一年以上大型软件项目总体设计.分析.架构经验,有移动互联网或云计算虚拟化系统设计开发经验者优先: 3 ...