Leetcode 215. Kth Largest Element in an Array[medium]

本文介绍了一种在未排序数组中查找第K大元素的有效算法。通过类似快速排序的方法将数组分为两部分,并确定目标元素位于哪一部分。此外,还提供了一个简单的排序查找方法作为对比。

题目:
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.


课上的例题,用类似快排的方法将数组分成两个集合:小于等于x的集合和大于x的集合。这样就可以确定第k大的数字处于哪个集合了,而另一个集合就不需要再搜索(递归)了。
时间复杂度,期望O(n)。
这里写图片描述

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        return find(nums, 0, nums.size() - 1, nums.size() + 1 - k);
    }

    int find(vector<int>& v, int lt, int rt, int k) {
        if (lt == rt) return v[lt];
        random_shuffle(v.begin() + lt, v.begin() + rt);
        if (v[rt] < v[rt - 1]) swap(v[rt], v[rt - 1]);
        int a = lt, b = rt - 1;
        bool p = 1;
        while (a != b) {
            if (v[a] <= v[b]) {
                if (p == 1) a++;
                else b--;
            }
            else {
                swap(v[a], v[b]);
                if (p == 1) b--, p = 0;
                else a++, p = 1;
            }
        }
        if (k <= a - lt + 1) return find(v, lt, a, k);
        else return find(v, a + 1, rt, k - (a - lt + 1));
    }
};

当然更直观的方法还是排序直接找第k大。
很尴尬,O(nlogn)的方法反而快一些。
这里写图片描述

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() - k];
    }
};
### LeetCode 215 - Kth Largest Element in an Array LeetCode215 题的目标是从一个未排序的数组中找到第 k 大的元素。可以采用多种方法来解决问题,其中最常见的是基于堆的方法以及快速选择算法。 #### 方法一:最小堆 (Min Heap) 通过维护大小为 `k` 的最小堆,可以在遍历整个数组的过程中动态调整堆结构以保留当前最大的前 `k` 个元素。最终,堆顶即为所求的第 `k` 大元素[^1]。 以下是实现代码: ```python import heapq def findKthLargest(nums, k): min_heap = [] for num in nums: if len(min_heap) < k: heapq.heappush(min_heap, num) elif num > min_heap[0]: heapq.heapreplace(min_heap, num) return min_heap[0] ``` 这种方法的时间复杂度主要由堆操作决定,整体时间复杂度为 \( O(n \log k) \),空间复杂度为 \( O(k) \)[^1]。 #### 方法二:快速选择 (Quickselect Algorithm) 快速选择是一种类似于快速排序的选择算法,其核心思想是利用分治策略将目标范围逐步缩小至所需位置。具体来说,在每次划分后可以根据索引定位所需的第 `k` 大元素所在区域并继续递归处理。 下面是具体的 Python 实现: ```python import random def partition(nums, left, right, pivot_index): pivot_value = nums[pivot_index] nums[right], nums[pivot_index] = nums[pivot_index], nums[right] store_index = left for i in range(left, right): if nums[i] > pivot_value: nums[store_index], nums[i] = nums[i], nums[store_index] store_index += 1 nums[right], nums[store_index] = nums[store_index], nums[right] return store_index def select(nums, left, right, k_smallest): if left == right: return nums[left] pivot_index = random.randint(left, right) pivot_index = partition(nums, left, right, pivot_index) if k_smallest == pivot_index: return nums[k_smallest] elif k_smallest < pivot_index: return select(nums, left, pivot_index - 1, k_smallest) else: return select(nums, pivot_index + 1, right, k_smallest) def findKthLargest(nums, k): n = len(nums) target_idx = n - k return select(nums, 0, n - 1, target_idx) ``` 此方法平均情况下具有线性时间复杂度 \( O(n) \),但在最坏情况下的时间复杂度可能退化到 \( O(n^2) \)。 --- ### 总结 对于本题而言,推荐优先考虑 **最小堆** 或者 **快速选择** 算法作为解决方案。前者更加稳定且易于理解;后者则在理论上具备更优的时间性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值