LeetCode 164. Maximum Gap[翻译]
164. 最大间隔
Given an unsorted array, find the maximum difference between the successive elements in its sorted form.
Return 0 if the array contains less than 2 elements.
给定一个未排序数组,找出该数组在有序形式时,连续元素之间最大的间隔。
Example 1:
Input: [3,6,9,1]
Output: 3
Explanation: The sorted form of the array is [1,3,6,9], either
(3,6) or (6,9) has the maximum difference 3.
示例 1:
输入:[3,6,9,1]
输出:3
解释:数组排序后的形式是[1,3,6,9],(3,6) 或者 (6,9)都是最大的距离,即3
Example 2:
Input: [10]
Output: 0
Explanation: The array contains less than 2 elements, therefore return 0. 示例2:
输入:[10]
输出:0
解释:数组所含元素小于2个,因此返回0
Note:
- You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
- Try to solve it in linear time/space.
注意:
- 你可以假定数组中所有元素都是非负整数并且适用于32位有符号的整数范围。
- 尝试在线性时间/空间内解决问题。
Solution
方案
Approach 3: Buckets and The Pigeonhole Principle
方式3:桶和鸽巢定理
Intuition
直觉
Sorting an entire array can be costly. At worst, it requires comparing each element with every other element. What if we didn't need to compare all pairs of elements? That would be possible if we could somehow divide the elements into representative groups, or rather, buckets. Then we would only need to compare these buckets.
对整个数组排序代价大。最坏的情况下,这需要让每个元素和其他元素进行比较。假设我们不需要比较所有邻近的元素呢?这是有可能的,如果我们能通过一种方式把元素划分到不同的组,或者说是桶。然后我们只需要对桶和桶进行比较。
Digression: The Pigeonhole Principle The Pigeonhole Principle states that if n items are put into m containers, with n > m, then at least one container must contain more than one item.
题外话:鸽巢原理 鸽巢原理规定,当n个物品被放入m个容器内,并且n>m时,得到至少有一个容器必然包含一个以上的物品。
Suppose for each of the n elements in our array, there was a bucket. Then each element would occupy one bucket. Now what if we reduced, the number of buckets? Some buckets would have to accommodate more than one element.
假设,对于数组中的n个元素的每一个元素,都有一个桶。然后,每个元素占据一个桶。现在假设我们减少,桶的数量?一些桶将不得不容纳超过一个元素。
Now let's talk about the gaps between the elements. Let's take the best case, where all elements of the array are sorted and have a uniform gap between them.This means every adjacent pair of elements differ by the same constant value. So for n elements of the array, there are n-1n−1 gaps, each of width, say, tt. It is trivial to deduce that t = (max - min)/(n-1)(where max and min are the minimum and maximum elements of the array). This width is the maximal width/gap between two adjacent elements in the array; precisely the quantity we are looking for!
现在让我们讨论元素间的间隔。让我们考虑最好的情况,即数组所有的元素都排好序并且它们之间有统一的间隔。这意味着每对相邻的元素相差着相同的不变值。所以对于有n个元素的数组,应当有n-1个间隔,它们的宽度,即,t,易于推导出 t = (max - min) / (n - 1) (max 和 min是数组元素的最大值和最小值(根据原文进行了纠正))。这个宽度是数组中相邻元素的最大宽度/间隔。恰恰是我们要找的数。
One can safely argue that this value of tt, is in fact, the smallest value that tt can ever accomplish of any array with the same number of elements (i.e. n) and the same range (i.e. (max - min)). To test this fact, you can start with a uniform width array (as described above) and try to reduce the gap between any two adjacent elements. If you reduce the gap between arr[i-1] and arr[i] to some value t - p, then you will notice that the gap between arr[i] and arr[i+1] would have increased to t + p. Hence the maximum attainable gap would have become t + p from t. Thus the value of the maximum gap t can only increase.
有人可以很有把握的提出这个值,t,是事实上,具有相同元素个数(即,n)和相同取值范围(即,(max - min))能做到的最小的 t。为了测试这个事实,你可以开始一个统一宽度的数组(如上所述),然后尝试减少任一两个相邻元素的间隔。如果你减少了arr[i - 1] 和 arr[i] 的间隔为 t - p, 然后你会注意到 arr[i] 和 arr[i + 1]的间隔增加到了 t + p. 因此,最大可得到的间隔从 t 变成了t + p
Buckets!
桶
Coming back to our problem, we have already established by application of the Pigeonhole Principle, that if we used buckets instead of individual elements as our base for comparison, the number of comparisons would reduce if we could accommodate more than one element in a single bucket. That does not immediately solve the problem though. What if we had to compare elements within a bucket? We would end up no better.
回到我们的问题,我们已经通过使用鸽巢原理建立起来,即如果我们使用桶代替单独的元素作为我们比较的基准,比较的数量将减少如果我们能使超过一个元素放入单个桶内。尽管这不会立即解决问题。如果我们不得不比较桶内元素怎么办?我们将得到不会更好的结果。
So the current motivation remains: somehow, if we only had to compare among the buckets, and not the elements within the buckets, we would be good. It would also solve our sorting problem: we would just distribute the elements to the right buckets. Since the buckets can be already ordered, and we only compare among buckets, we wouldn't have to compare all elements to sort them!
所以,目前的动机依然是:以某种方式,如果我们仅仅是不得不在桶间进行比较,并且不是比较桶内元素,我们将得到不错的结果。它也将解决我们的排序问题:我们将仅需把元素分配到正确的桶内。由于桶可以是已经有序的,并且我们只在桶间比较,所以,我们将不至于不得不比较所有元素去排序。
But if we only had buckets to compare, we would have to ensure, that the gap between the buckets itself represent the maximal gap in the input array. How do we go about doing that?
但是,如果我们仅对桶进行比较,我们将不得不保证,桶之间的间隔本身代表整个输入数组的最大间隔。我们如何做到这个呢?
We could do that just by setting the buckets to be smaller than t = (max - min)/(n-1) (as described above). Since the gaps (between elements) within the same bucket would only be ≤t, we could deduce that the maximal gap would indeed occur only between two adjacent buckets.
我们可以实现它,通过设置桶大小小于 t = (max - min) / (n - 1) (如上所示). 由于同一桶内元素间的间隔只能 <= t, 我们可以推断出,最大的间隔将的确出现仅出现在两个相邻的桶之间
Hence by setting bucket size b to be 1 < b ≤(max−min)/(n−1), we can ensure that at least one of the gaps between adjacent buckets would serve as the maximal gap.
因此,通过设置桶大小b为 1 < b <= (max - min) / (n - 1). 我们能确保至少有一个相邻的桶之间的间隔将是最大间隔
Clarifications
说明
A few clarifications are in order:
以下是一些说明:
Would the buckets be of uniform size? Yes. Each of them would be of the same size b.
- 桶会是统一的大小吗?是的,任一一个都是同样的大小 b.
But, then wouldn't the gap between them be uniform/constant as well? Yes it would be. The gap between them would be 1 integer unit wide. That means a two adjacent buckets of size 3 could hold integers with values, say, 3 - 6 and 7 - 9. We avoid overlapping buckets.
- 但是,桶之间的间隔也不会是统一/相同的大小吗?是的,它会是(统一的大小)。桶之间的间隔是1个整数单位宽度。这意味着一个两个相邻的大小为3的桶可以装入整数,比如,3-6 和 7-9. 我们避免互相覆盖的桶。
Then what are you talking about when you say the gap between two adjacent buckets could be the maximal gap? When we are talking about the size of a bucket, we are talking about its holding capacity. That is the range of values the bucket can represent (or hold). However the actual extent of the bucket are determined by the values of the maximum and minimum element a bucket holds. For example a bucket of size 5 could have a capacity to hold values between 6 - 10. However, if it only holds the elements 7,8 and 9, then its actual extent is only (9 - 7) + 1 = 3 which is not the same as the capacity of the bucket.
- 然后,当你说两个相邻的桶的间隔是最大间隔的时候是在说什么呢?当我们讨论桶大小时,我们将讨论桶的容量。即桶能表示(容纳)的值的范围。然而,桶的实际长度由桶容纳的元素的最大值和最小值决定的。举例,大小为5的桶拥有的容量能容纳值6-10.然后,如果它值容纳了元素7,8和9,然后它的实际长度仅仅是(9 - 7) + 1 = 3 这和桶的实际容量不一样。
Then how do you compare adjacent buckets? We do that by comparing their extents. Thus we compare the minimum element of the next bucket to the maximum element of the current bucket. For example: if we have two buckets of size 5 each, holding elements [1,2,3] and [9, 10] respectively, then the gap between the buckets would essentially refer to the value 9 - 3 = 6 (which is larger than the size of either bucket).
- 然后,你如何比较相邻的桶?我们通过比较桶的长度去实现它。因此我们比较下一个桶的最小元素和当前桶的最大元素。举例:如果我们有两个大小都是 5 的桶,分别拥有元素[1, 2, 3] 和 [9, 10],然后两个桶之间的间隔必然指向值 9 - 3 = 6 (该值大于两个桶的任一一个桶的大小)
But then aren't we comparing elements again?! We are, yes! But only compare about twice the elements as the number of buckets (i.e. the minimum and maximum elements of each bucket). If you followed the above, you would realize that this amount is certainly less than the actual number of elements in the array, given a suitable bucket size was chosen.
- 但是,然后我们不再比较元素了吗?是的,我们会比较。但是,仅比较两倍于桶数量的次数(即,每个桶的最小和最大元素)。如果你按照上面的做,选一个合适大小的桶大小,你将意识到(比较的)数量当然少于实际数组元素的数量
Algorithm
算法
We choose a bucket size b such that 1 < b ≤(max−min)/(n−1). Let's just choose b=⌊(max−min)/(n−1)⌋.
- 我们选择桶大小 b 满足 1 < b <= (max - min) / (n - 1). 让我们选择 b = ⌊(max−min)/(n−1)⌋.
Thus all the n elements would be divided among k=⌈(max−min)/b⌉ buckets.
- 因此,所有 n 个元素将被划分到 ⌈(max−min)/b⌉ 个桶中
Hence the i^{th} bucket would hold the range of values:[min+(i−1)∗b, min+i∗b) (
1-based indexing).- 因此,第 i 个桶拥有的值范围是: [min+(i−1)∗b, min+i∗b) (
1开始的索引). It is trivial to calculate the index of the bucket to which a particular element belongs. That is given by ⌊(num−min)/b⌋ (
0-based indexing) where num is the element in question.- 易于计算出某个元素所属于的桶。通过 ⌊(num−min)/b⌋ (
0开始的索引)计算,其中 num 就是某个元素。
- Once all n elements have been distributed, we compare k-1 adjacent bucket pairs to find the maximum gap.
- 一旦全部 n 个元素都被分配完,我们比较 k - 1 个相邻的桶对找出最大间隔。
class Bucket {
public:
bool used = false;
int minval = numeric_limits<int>::max(); // same as INT_MAX
int maxval = numeric_limits<int>::min(); // same as INT_MIN
};
int maximumGap(vector<int>& nums)
{
if (nums.empty() || nums.size() < 2)
return 0;
int mini = *min_element(nums.begin(), nums.end()),
maxi = *max_element(nums.begin(), nums.end());
int bucketSize = max(1, (maxi - mini) / ((int)nums.size() - 1)); // bucket size or capacity
int bucketNum = (maxi - mini) / bucketSize + 1; // number of buckets
vector<Bucket> buckets(bucketNum);
for (auto&& num : nums) {
int bucketIdx = (num - mini) / bucketSize; // locating correct bucket
buckets[bucketIdx].used = true;
buckets[bucketIdx].minval = min(num, buckets[bucketIdx].minval);
buckets[bucketIdx].maxval = max(num, buckets[bucketIdx].maxval);
}
int prevBucketMax = mini, maxGap = 0;
for (auto&& bucket : buckets) {
if (!bucket.used)
continue;
maxGap = max(maxGap, bucket.minval - prevBucketMax);
prevBucketMax = bucket.maxval;
}
return maxGap;
}
//Java version, @author: Daneil Tan
class Bucket {
public int max = Integer.MIN_VALUE;
public int min = Integer.MAX_VALUE;
}
class Solution {
public int maximumGap(int[] nums) {
if (nums.length < 2) return 0;
int max = Arrays.stream(nums).max().getAsInt();
int min = Arrays.stream(nums).min().getAsInt();
//Bucket size or capacity
int bucketSize = Math.max(1, (max - min) / (nums.length - 1));
//Number of buckets
int bucketNum = (max - min) / bucketSize + 1;
Bucket[] buckets = new Bucket[bucketNum];
for (int num : nums) {
int bucketIdx = (num - min) / bucketSize;
if (buckets[bucketIdx] == null) buckets[bucketIdx] = new Bucket();
buckets[bucketIdx].max = Math.max(buckets[bucketIdx].max, num);
buckets[bucketIdx].min = Math.min(buckets[bucketIdx].min, num);
}
int maxGap = 0, prevBucketMax = min;
for (int i = 0; i < buckets.length; i++) {
if (buckets[i] == null) continue;
if (buckets[i].min - prevBucketMax > maxGap)
maxGap = buckets[i].min - prevBucketMax;
prevBucketMax = buckets[i].max;
}
return maxGap;
}
}
Complexity Analysis
复杂度分析
Time complexity: O(n+b)≈O(n).
时间复杂度:O(n+b)≈O(n).
Distributing the elements of the array takes one linear pass (i.e. O(n) complexity). Finding the maximum gap among the buckets takes a linear pass over the bucket storage (i.e. O(b) complexity). Hence overall process takes linear runtime.
分配数组的元素花费一次线性遍历(即,O(n)复杂度). 找到桶间的最大间隔在桶大小上花费了一次线性遍历(即,O(b)复杂度)。因此,整个过程花费了线性运行时间。
Space complexity: O(2⋅b)≈O(b) extra space.
空间复杂度:O(2⋅b)≈O(b) 额外空间.
Each bucket stores a maximum and a minimum element. Hence extra space linear to the number of buckets is required.
每个桶存储了最大元素和最小元素。因此,和桶大小一样的额外空间是必要的。
英文原文链接:https://leetcode.com/problems/maximum-gap/solution/
LeetCode 164. Maximum Gap[翻译]的更多相关文章
- leetcode[164] Maximum Gap
梅西刚梅开二度,我也记一题. 在一个没排序的数组里,找出排序后的相邻数字的最大差值. 要求用线性时间和空间. 如果用nlgn的话,直接排序然后判断就可以了.so easy class Solution ...
- [LeetCode] 164. Maximum Gap 求最大间距
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- ✡ leetcode 164. Maximum Gap 寻找最大相邻数字差 --------- java
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- Java for LeetCode 164 Maximum Gap
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- 【LeetCode】164. Maximum Gap (2 solutions)
Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...
- 【刷题-LeetCode】164 Maximum Gap
Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...
- 【leetcode】Maximum Gap
Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...
- 【Leetcode】164. Maximum Gap 【基数排序】
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
- 【leetcode】Maximum Gap(hard)★
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
随机推荐
- redis(九):Redis 哈希(Hash)(python)
# -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host="123.56.74.190& ...
- python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
- JS中this指向的更改
JS中this指向的更改 JavaScript 中 this 的指向问题 前面已经总结过,但在实际开中, 很多场景都需要改变 this 的指向. 现在我们讨论更改 this 指向的问题. call更改 ...
- IOS10 window.navigator.geolocation.getCurrentPosition 无法定位问题
在iOS 10中,苹果对webkit定位权限进行了修改,所有定位请求的页面必须是https协议的. 如果是非https网页,在http协议下通过HTML5原生定位接口会返回错误,也就是无法正常定位到用 ...
- Android 性能优化 ---- 内存优化
1.Android内存管理机制 1.1 Java内存分配模型 先上一张JVM将内存划分区域的图 程序计数器:存储当前线程执行目标方法执行到第几行. 栈内存:Java栈中存放的是一个个栈帧,每个栈帧对应 ...
- Python 实现图像快速傅里叶变换和离散余弦变换
图像的正交变换在数字图像的处理与分析中起着很重要的作用,被广泛应用于图像增强.去噪.压缩编码等众多领域.本文手工实现了二维离散傅里叶变换和二维离散余弦变换算法,并在多个图像样本上进行测试,以探究二者的 ...
- 设计模式:observer模式
目标:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新 例子: class Observer //观察者 { public: virtual vo ...
- Java中解决继承和接口默认方法冲突
1)超类优先.如果超类提供了一个具体方法,同名而且有相同参数类型发默认方法会被忽略. 2)接口冲突.如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型(不论是否是默认参数)相同的方 ...
- centos7 安装 isign
centos应该自带python和openssl,这两个就不用装了, 先安装zip和git yum install -y unzip zip yum install git 然后克隆代码: https ...
- Servlet学习之Tomcat控制台中文乱码问题
Tomcat控制台中文乱码问题 在更新了IDEA2020.1版本后,可以安装官方的简体中文插件,方便我们日常使用,但是更新后再运行Tomcat时,控制台的输出日志出现中文乱码问题,接下来告诉大家如何修 ...