题目描述:
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
程序代码:
class Solution {
public:
// 用于分治算法的函数,将数组分割
int par(vector<int>& nums, int low, int high) {
// 题意中k绝对有效,所以不用考虑无效问题
// 取第一个数(为了方便)为枢v
int v = nums[low];
// 将所有大于枢v的数放到v左边,小于v的放到v右边
while (high > low) {
while (high > low && nums[high] <= v) {
high--;
}
// 和下面一起起到swap的作用
nums[low] = nums[high];
while (high > low && nums[low] >= v) {
low++;
}
nums[high] = nums[low];
}
nums[low] = v;
// 返回枢v所在的位置
return low;
}
// 寻找第k大数的函数
int findKthLargest(vector<int>& nums, int k) {
int low = 0;
int high = nums.size() - 1;
// 用循环替代递归,防止空间复杂度过大
while (true) {
// 枢的位置pos
int pos = par(nums, low, high);
// k在枢左边
if (k < pos + 1) {
high = pos - 1;
}
// 循环直到枢的位置和k一致(注意有差一个1)
else if (k == pos + 1) {
return nums[pos];
}
// k在枢右边
else {
low = pos + 1;
}
}
}
};
简要题解:
这周开始复习前面的内容,因此选了这题分治算法的题目来做。
先理解题意。本题输入为一串数组和一个数k,要求找出数组中第k大的数并输出。(假设k有效)
本题类似课上所讲到过的selection问题,我选做这题算是对这类问题的一个练习和复习。用分治算法处理这种问题时,可以取出一个数v作为枢,然后将数组分为三组,即小于v的部分,等于v的部分,大于v的部分。当枢v的位置pos与k相等时(可能由于数组的处理原因差一个1,且这里数组需要枢左边的数比枢大,右边比枢小),这个位置的元素nums[pos]即可作为输出;否则,用循环或递归的方法从这剩余两组中再进一步细化找出最终的输出。
其实这种分治算法类似快速排序的处理方法,因此我在写代码时参考了快速排序算法的写法。用一个par函数作为将数组分割的函数,传入的参数有数组nums, 左端标low,右端标high。取数组中第一个数为枢v(这里只是为了方便所以取第一个数),接着可以用循环将小于v的数都交换到v的右边,大于v的数都交换到v的左边。函数par最终返回v的位置。在findKthLargest函数中,则用循环的方法,判断k与pos之间的位置关系,根据之前所提到的方法最终找到输出。需要注意的是,理论上用递归的方法也可以,不过本题中我尝试用递归方法导致了空间复杂度过高,因此我采用了循环的方法。
此外本题直接用stl库中的sort方法可以很简单的得出答案,不过就没有用到分治算法了,因此这里不提。
通过本题我重新复习了一下分治算法。接下来我还会对之前所做的一些算法类型的题目类型进行复习。