[LeetCode无序数组K小元素] | 刷题打卡
一直有刷题习惯,最近才看到掘金举办了刷题活动,特来参加!此题为第12题。不得不说掘金的主题就是漂亮呀!赞。
本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
描述 找到一个无序数组中第K小的数 样例
样例 1:
输入: [3, 4, 1, 2, 5], k = 3
输出: 3
样例 2:
输入: [1, 1, 1], k = 2
输出: 1
挑战
O(nlogn)的算法固然可行, 但如果你能 O(n) 解决, 那就非常棒了.
二、思路分析:
最简单的是直接排序,选择第k个位置的值,时间复杂度是;这里使用推荐双指针+快速排序模板
方法 | 描述 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|
| 双指针法(形似) | 只是用了两根指针,相向双指针,核心思想用的是快速排序 |
partition步骤:
- 令
left = start,right = end,pivot = nums[left]。 - 当
nums[left] < pivot时,left指针向右移动。 - 当
nums[right] > pivot时,right指针向左移动。 - 交换两个位置的值,
right指针左移,left指针右移。 - 直到两指针相遇,否则回到第2步。
每次partition后根据pivot的位置,寻找下一个搜索的范围。
三、AC 代码:
public class Solution {
/**
* @param k: An integer
* @param nums: An integer array
* @return: kth smallest element
*/
public int kthSmallest(int k, int[] nums) {
return quickSelect(nums, 0, nums.length - 1, k - 1);
}
/**
*
* @param nums
* @param i
* @param j
* @param k
* @return
*/
private int quickSelect(int[] nums, int start, int end, int k) {
if (start == end) {
return nums[start];
}
int left = start;
int right = end;
int pivot = nums[(start + end) / 2];
while (left <= right) {
while (left <= right && nums[left] < pivot) {
left++;
}
while (left <= right && nums[right] > pivot) {
right--;
}
if (left <= right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
// conditions
if (right >= k && right >= start) {
return quickSelect(nums, start, right, k);
} else if (left <= k && left <= end) {
return quickSelect(nums, left, end, k);
}
return nums[k];
}
}
四、总结:
此题可以归为双指针算法类型的题目,也可以归为划分算法类的题目,可以配合第11题来食用更佳!
- 形式上是双指针的变体,使用了
left、right、pivot三根指针 - 这题其实是快速排序算法的变体,通过快速排序算法的
partition步骤,可以将小于pivot的值划分到pivot左边,大于pivot的值划分到pivot右边,所以可以直接得到pivot的范围。从而缩小范围继续找第k大的值。