查找数组中的 K 个最小元素
Posted
技术标签:
【中文标题】查找数组中的 K 个最小元素【英文标题】:Find K Smallest Elements in an Array 【发布时间】:2021-01-13 00:08:00 【问题描述】:我想在一个数组中找到 K 个最小的元素,并且我基本上能够将我的数组排序为一个最小堆结构,但我仍然得到错误的输出。
这是我的输入:
arr = [9,4,7,1,-2,6,5]
k = 3
这是代码:
public static int[] findKSmallest(int[] arr, int k)
int[] result = new int[k];
int heapSize = arr.length;
// Write - Your - Code
for (int i = (heapSize - 1) / 2; i >= 0; i--)
minHeap(arr, i, heapSize);
for (int j = 0; j < k; j++)
result[j] = arr[j];
return result;
public static void minHeap(int[] arr, int index, int heapSize)
int smallest = index;
while (smallest < heapSize / 2)
int left = (2 * index) + 1; // 1 more than half the index
int right = (2 * index) + 2; // 2 more than half the index
if (left < heapSize && arr[left] < arr[index])
smallest = left;
if (right < heapSize && arr[right] < arr[smallest])
smallest = right;
if (smallest != index)
int temp = arr[index];
arr[index] = arr[smallest];
arr[smallest] = temp;
index = smallest;
else
break;
这是我的预期输出:
[-2,1,4]
虽然我的输出是:
[-2,1,5]
我想知道我哪里出错了。
【问题讨论】:
【参考方案1】:构建 minHeap 后,您必须提取元素并适当调整树。您只需按索引从数组中获取元素,这不是堆的工作方式。
我稍微修改了您的minHeap()
方法以使用recursion
,您应该检查arr[smallest] < arr[left]
而不是相反的方式。
public static int[] findKSmallest(int[] arr, int k)
int[] result = new int[k];
int heapSize = arr.length;
// Write - Your - Code
for (int i = (heapSize - 1) / 2; i >= 0; i--)
minHeap(arr, heapSize, i);
// extract elements from heap
for (int i = heapSize - 1; i > 0; i--)
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
minHeap(arr, 0, i);
for (int j = 0; j < k; j++)
result[j] = arr[j];
return result;
public static void minHeap(int[] arr, int index, int heapSize)
int smallest = index;
int left = (2 * index) + 1; // 1 more than half the index
int right = (2 * index) + 2; // 2 more than half the index
if (left < heapSize && arr[smallest] < arr[left])
smallest = left;
if (right < heapSize && arr[smallest] < arr[right])
smallest = right;
if (smallest != index)
int temp = arr[index];
arr[index] = arr[smallest];
arr[smallest] = temp;
minHeap(arr, smallest, heapSize);
希望这会有所帮助。不出所料,结果是:
[-2, 1, 4]
【讨论】:
【参考方案2】:从 Java 8 开始我们可以对流进行排序
替代代码:
Arrays.stream(arr).sorted().boxed().collect(Collectors.toList()).subList(0, k);
地点:
int[] arr = 9,4,7,1,-2,6,5;
int k = 3; // toIndex
上下文和测试平台中的替代代码:
public static void main(String[] args)
int[] arr = 9, 4, 7, 1, -2, 6, 5;
int k = 3; // toIndex
List<Integer> listResult = Arrays.stream(arr)
.sorted().boxed().collect(Collectors.toList()).subList(0, k);
// print out list result
System.out.println("Output of list result: " + listResult);
int[] arrayResult = listResult.stream().mapToInt(i -> i).toArray();
// print out array result
List<String> arrayResultAsString = Arrays.stream(arrayResult)
.boxed().map(i -> String.valueOf(i)).collect(Collectors.toList());
System.out.println("Output of array result: " + arrayResultAsString);
输出:
Output of list result: [-2, 1, 4]
Output of array result: [-2, 1, 4]
【讨论】:
【参考方案3】:你可以使用Arrays.stream(int[])
方法:
int[] arr = 9, 4, 7, 1, -2, 6, 5;
int k = 3;
int[] minHeap = Arrays.stream(arr).sorted().limit(k).toArray();
System.out.println(Arrays.toString(minHeap)); // [-2, 1, 4]
【讨论】:
【参考方案4】:如果 K 相对于数组大小相对较小,我的建议是使用选择排序,因此它可能是一种设计模式策略 - 取决于 K 与数组大小的关系,例如两个过程:小 K 的选择排序和快速排序巨大的 K。与其玩设计模式,不如使用简单的 if 语句,例如选择
【讨论】:
以上是关于查找数组中的 K 个最小元素的主要内容,如果未能解决你的问题,请参考以下文章
使用 max heapify 在数组中查找第 k 个最小元素的时间复杂度
堆的相关习题 面试题17.14最小的K个数 347前K个高频元素 373查找和最小的K对数字