题意描述:
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
0 <= k <= arr.length <= 1000
0 <= arr[i] <= 1000
示例:
一:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
二:
输入:arr = [0,1,2,1], k = 1
输出:[0]
解题思路:
Alice: 可以直接排序,然后返回数组中前 K 个元素。
Bob:恩,题目中给出了数组元素的范围,也可以用桶排序的方法记录每个元素出现的次数。然后在标记数组中从前往后,找出K个元素就好了。
Alice: 恩,排序要 O(n * log n)
的时间复杂度,桶排序的方法要 O(n)
的空间复杂度,时间复杂度也是O(n)。
Bob: 空间换时间嘛。
Alice: 我发现你很喜欢用 break
呀,这样是不是不太好。
Bob: 好像是的,这样子逻辑上不太顺畅。
代码:
Python 方法一: “桶排序思想”
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
if k == 0:
return []
ret = []
cnt = [0 for x in range(10001)]
for x in arr:
cnt[x] += 1
for x in range(len(cnt)):
if cnt[x] > 0:
ret.extend([x for z in range(cnt[x])])
if len(ret) >= k:
break
while len(ret) > k:
ret.pop(-1)
return ret
Java 方法一: 排序 + copy 数组
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int[] ret = new int[k];
Arrays.sort(arr);
for(int i=0; i<k; ++i){
ret[i] = arr[i];
}
return ret;
}
}
Java 方法二: 桶排序
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int[] cnt = new int[10001];
int[] ret = new int[k];
for(int x : arr){
cnt[x] ++;
}
int retIndex = 0;
for(int index=0; index<cnt.length; ++index){
if(cnt[index] > 0){
int tmp = 0;
while(tmp < cnt[index] && retIndex < k){
ret[retIndex++] = index;
tmp++;
}
}
if(retIndex == k){
break;
}
}
return ret;
}
}
易错点:
-
经测试,输入数组中元素的实际范围是
[0,10000]
-
一些测试点:
[3,2,1]
2
[0,1,2,1]
1
[0,0,0,2,0,5]
0
[0,0,1,3,4,5,0,7,6,7]
9
- 答案:
[1,2]
[0]
[]
[0,0,0,1,3,4,5,6,7]
总结: