最开始的想法很简单,直接食用sort()将数组排序,然后直接通过序号取第K大的元素即可。sort()使用的是优化后的快速排序,所以时间复杂度平均为O(nlogn),空间复杂度为O(logn)。
不满足题目要求,此时注意到题目中还特意给出了数组大小n,可能需要用到别的解法才能达到题目要求。

class Solution {
public:
    int findKth(vector<int> a, int n, int K) {
        // write code here
        sort(a.begin(),a.end());
        return a.at(a.size()-K);
    }
};

在查阅相关资料后并未找到空间复杂度为O(1)的解法,如果说不借助辅助变量,则快速排序可满足,但快速排序的递归深度较大,虽不借助辅助变量,但递归的栈深度使其空间复杂度为O(logn)。当然,上面给出的简短的两行代码当然并非最优解,还有较大优化空间。
一种优化方法是在快排基础之上优化,每趟快排都查看分界元素的位置,若大于K,则只对左侧元素排序,若小于K则只对右侧元素排序,这样每趟递归都可以减少一定的时空复杂度。代码如下。从最终运行结果来看,运行时间上是有明显提升的,而运行空间上的提升则较小。这种优化方法要求必须熟练手搓快排,对基础有一定要求。像我老是偷个懒用库函数的,写起来就坑比较多。还是那句话,基础不牢,地动山摇。
另一种优化方法是使用堆排序,这种方法仅在数据量足够大时才可被称为优化。

class Solution {
public:
    int qs(vector<int>& a,int low, int high,int k){
        if(high <= low){
            return a.at(k-1);
        }
        int i = low;
        int j = high+1;
        while(1){
            while(a.at(++i) > a.at(low)){
                if(i == high){
                    break;
                }
            }
            while(a.at(--j) < a.at(low)){
                if(j == low){
                    break;
                }
            }
            if(i>=j){
                break;
            }
            int temp = a.at(i);
            a.at(i) = a.at(j);
            a.at(j) = temp;
        }
        int tmp = a.at(low);
        a.at(low) = a.at(j);
        a.at(j) = tmp;
        if(j == k-1){
            return a.at(j);
        }
        if(j > k-1){
            return qs(a,low,j-1,k);
        }
        if(j < k-1){
            return qs(a,j+1,high,k);
        }
        return 0;

    }
    int findKth(vector<int> a, int n, int K) {
        // write code here
        return qs(a, 0, n-1, K);
    }
};