215. Kth Largest Element in an Array 第 K 大的数

215. Kth Largest Element in an Array 第 K 大的数

第一次解法

从大到小排序然后输出 K-1 的元素 时间复杂度: n(logn)

int findKthLargest(vector<int>& nums, int k) {
    sort(nums.begin(), nums.end(), greater<int>());
    return nums[k-1];
}

快速选择

时间复杂度:平均 O(n) 与快排一模一样的 Partition 分割函数,但是分治的依据不同,而且有序的查找我们只需要单边处理即可

int findKthLargest(vector<int>& nums, int k) {
	// 找第K大可以转化成找从小到大排序后 len-k 位置的元素
    k=nums.size()-k;
    int lo=0;
    int hi=nums.size()-1;
    while(lo<hi) {
        int i=partition(nums, lo, hi);
		// 前K个的元素都比主元小,找到
        if (i==k) {
            break;
        } else if (i>k) {
			// 多于 K 个元素比主元小,目标一定在前半边
            hi=i-1;
        } else {
			// 少于 K 个元素比主元小,那么目标一定在后半边
            lo=i+1;
        }
    }
    return nums[k];
}

// 与快排一致的分治排序算法
int partition(vector<int>& nums, int st, int end) {
    int pivot=nums[end];
    int i=st-1;
    for(int j=st;j<end;++j) {
        if (nums[j]<pivot) {
            ++i;
            swap(nums[i], nums[j]);
        }
    }
    swap(nums[end], nums[i+1]);
    return i+1;
}

堆解法 — 适用于海量数据

时间复杂度:nlog(k) 适用于 n 很大而 k 较小的情况

  • 使用最大堆,一次性构建然后取 K 次
  • 使用最小堆,构建 K 个元素的最小堆,然后容量超过 K 之后判断堆顶元素是否小于插入元素,如果是,则弹出堆顶并插入新元素,一直维护到数据末尾即可
  • 使用 set 或者 multiset 这种有序容器,道理类似

#堆