原题网址:https://leetcode.com/problems/maximum-gap/
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.
方法一:先排序在查找。
public class Solution {
public int maximumGap(int[] nums) {
if (nums == null || nums.length < 2) return 0;
Arrays.sort(nums);
int max = 0;
for(int i=1; i<nums.length; i++) {
max = Math.max(max, nums[i]-nums[i-1]);
}
return max;
}
}
方法二:桶排序+鸽笼原理。
public class Solution {
public int maximumGap(int[] nums) {
if (nums == null || nums.length < 2) return 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int num: nums) {
if (num < min) min = num;
if (num > max) max = num;
}
if (max - min == 0) return 0;
int width = (max-min)/nums.length + 1;
int[] heights = new int[nums.length];
int[][] buckets = new int[nums.length][2];
for(int num: nums) {
int bucket = (num-min) / width;
if (heights[bucket]==0) {
buckets[bucket][0] = num;
heights[bucket] = 1;
} else if (heights[bucket]==1) {
buckets[bucket][1] = Math.max(num, buckets[bucket][0]);
buckets[bucket][0] = Math.min(num, buckets[bucket][0]);
heights[bucket] = 2;
} else {
buckets[bucket][0] = Math.min(num, buckets[bucket][0]);
buckets[bucket][1] = Math.max(num, buckets[bucket][1]);
}
}
int maxGap = 0;
int previous = buckets[0][heights[0]-1];
for(int i=1; i<buckets.length; i++) {
if (heights[i] == 0) continue;
if (buckets[i][0] - previous > maxGap) maxGap = buckets[i][0] - previous;
previous = buckets[i][heights[i]-1];
}
return maxGap;
}
}
可以换一种计算桶宽的方法:
public class Solution {
public int maximumGap(int[] nums) {
if (nums == null || nums.length < 2) return 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int num: nums) {
if (num < min) min = num;
if (num > max) max = num;
}
if (max - min == 0) return 0;
int width = Math.max(1, (max-min)/nums.length);
int[] heights = new int[(max-min)/width+1];
int[][] buckets = new int[(max-min)/width+1][2];
for(int num: nums) {
int bucket = (num-min) / width;
if (heights[bucket]==0) {
buckets[bucket][0] = num;
heights[bucket] = 1;
} else if (heights[bucket]==1) {
buckets[bucket][1] = Math.max(num, buckets[bucket][0]);
buckets[bucket][0] = Math.min(num, buckets[bucket][0]);
heights[bucket] = 2;
} else {
buckets[bucket][0] = Math.min(num, buckets[bucket][0]);
buckets[bucket][1] = Math.max(num, buckets[bucket][1]);
}
}
int maxGap = 0;
int previous = buckets[0][heights[0]-1];
for(int i=1; i<buckets.length; i++) {
if (heights[i] == 0) continue;
if (buckets[i][0] - previous > maxGap) maxGap = buckets[i][0] - previous;
previous = buckets[i][heights[i]-1];
}
return maxGap;
}
}
也可以使用哈希映射来作为桶:
public class Solution {
public int maximumGap(int[] nums) {
if (nums == null || nums.length <= 1) return 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int num: nums) {
min = Math.min(min, num);
max = Math.max(max, num);
}
if (min == max) return 0;
int size = Math.max(1, (max-min)/nums.length);
Map<Integer, Bucket> buckets = new HashMap<>();
for(int num: nums) {
int key = (num-min)/size;
Bucket bucket = buckets.get(key);
if (bucket == null) {
bucket = new Bucket(num);
buckets.put(key, bucket);
} else {
bucket.put(num);
}
}
int gap = 0;
Bucket prev = buckets.get(0);
for(int i=1; i<=(max-min)/size; i++) {
Bucket bucket = buckets.get(i);
if (bucket == null) continue;
gap = Math.max(gap, bucket.min() - prev.max());
prev = bucket;
}
return gap;
}
}
class Bucket {
int[] vals = new int[2];
int count = 0;
Bucket(int val) {
vals[0] = val;
count = 1;
}
int max() {
return vals[count-1];
}
int min() {
return vals[0];
}
void put(int val) {
if (count == 1 && vals[0] == val) return;
else if (count == 1 && vals[0] < val) vals[count++] = val;
else if (count == 1 && vals[0] > val) {
vals[1] = vals[0];
vals[0] = val;
count = 2;
} else if (val < vals[0]) vals[0] = val;
else if (val > vals[1]) vals[1] = val;
}
}