要在一个无序数组中找到第 K 小的数,可以使用快速选择算法(Quickselect)。
public int findKthSmallest(int[] nums, int k) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int partitionIndex = partition(nums, left, right);
if (partitionIndex == k - 1) return nums[partitionIndex];
if (partitionIndex < k - 1) left = partitionIndex + 1;
else right = partitionIndex - 1;
}
return -1;
}
private int partition(int[] nums, int left, int right) {
int pivot = nums[right];
int partitionIndex = left;
for (int i = left; i < right; i++) {
if (nums[i] <= pivot) {
swap(nums, i, partitionIndex);
partitionIndex++;
}
}
swap(nums, right, partitionIndex);
return partitionIndex;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
算法流程:
- 将数组下标 left 到 right 看作一个区间。
- 选择区间最后一个数作为枢轴 pivot。
- 从区间左边开始遍历,小于 pivot 的数停下来,将其与区间左端点互换。
- 将 pivot 与换过来的数互换。此时 pivot 的位置就是它在区间内部的最终位置。
- 根据 pivot 的最终位置和 k 的大小判断下一步的区间范围是在 pivot 的左边还是右边。
- 重复上述步骤直到找到第 k 小的数。
时间复杂度 O(n),空间复杂度 O(1)。
所以,在无序数组中找到第 K 小数的关键是:
- 使用快速排序的 partition 操作划分数组。
- 根据 partition 结果缩小搜索区间,递归查找。
- 特殊情况,如果数组长度为 1,直接返回。