Leetcode 215、数组中第k个最大的元素

题目链接kth-largest-element-in-an-array

方法1:

使用快速排序。

1、对数组进行partition,从left到right随机选择一个主元pivot,将pivot与left的元素交换位置。

另索引 j 初始为left,扫描从left + 1到right的元素,若小于pivot,则将其与 ++j 处的元素交换。

这样当扫描结束,left的元素即主元pivot,从left + 1到 j 的元素都大于pivot,从 j + 1到right的元素都小于等于pivot。

将left位置的元素与 j 位置的互换,则从left到 j-1 的元素都大于pivot,j 位置元素等于pivot,j 右边元素都小于等于pivot。

因此partition完成。返回pivot的位置 j。

2、若pivot的下标 idx 等于 k - 1,则pivot位置的元素即第K大的元素。

 若idx大于 k - 1,另right = idx - 1,返回第一步在左边寻找。

若idx小于 k - 1,另left = idx + 1,返回第一步在右边寻找。

code:

 1 class Solution:
 2 
 3     def findKthLargest(self, nums: List[int], k: int) -> int:
 4         def partition(nums, left, right):
 5             pivot_idx = random.randint(left, right)
 6             if nums[pivot_idx] != nums[left]:
 7                 nums[left], nums[pivot_idx] = nums[pivot_idx], nums[left]
 8             pivot = nums[left]
 9 
10             j = left
11             for i in range(left + 1, right + 1):
12                 if nums[i] > pivot:
13                     j += 1 
14                     nums[j], nums[i] = nums[i], nums[j]
15             # nums[left] = pivot,nums[left+1...j] > pivot,交换后nums[left..j-1] > pivot,nums[j] = pivot,nums[j+1...right] <= pivot
16             if nums[j] != nums[left]:
17                 nums[j], nums[left] = nums[left], nums[j]
18             return j
19 
20         left = 0
21         right = len(nums) - 1
22         while True:
23             idx = partition(nums, left, right)
24             if idx == k - 1:
25                 return nums[idx]
26             elif idx > k - 1:
27                 right = idx - 1
28             else:
29                 left = idx + 1

方法2:

用优先队列实现。

1、可以用小顶堆,维护K个最大的元素。

先将数组前K个元素入堆,遍历数组的元素,当某元素大于堆顶元素,则堆顶出堆,将此元素加入。

最终堆顶元素即第K大的元素。

2、可用大顶堆,维护N - K + 1个最小的元素,这是因为第K大即第N - K + 1 小。

先将数组前N - K + 1个元素入堆,遍历数组的元素,当某元素小于堆顶元素,则堆顶出堆,将此元素加入。

最终堆顶元素即第K大的元素。

3、时间复杂度为O(NlogK),空间复杂度为O(K),因此当K < N / 2,用小顶堆,否则大顶堆。

code:

 1 class Solution {
 2 public:
 3     int findKlarge(vector<int>& nums, int k) {
 4         priority_queue<int, vector<int>, greater<int>> pq; //小顶堆
 5         for (int i = 0; i < k; i++) {
 6             pq.push(nums[i]);
 7         }
 8         for (int i = k; i < nums.size(); i++) {
 9             if (nums[i] > pq.top()) {
10                 pq.pop();
11                 pq.push(nums[i]);
12             }
13         }
14         return pq.top();
15     }
16 
17     int findKsmall(vector<int>& nums, int k) {
18         priority_queue<int> pq; //默认大顶堆
19         for (int i = 0; i < k; i++) {
20             pq.push(nums[i]);
21         }
22         for (int i = k; i < nums.size(); i++) {
23             if (nums[i] < pq.top()) {
24                 pq.pop();
25                 pq.push(nums[i]);
26             }
27         }
28         return pq.top();
29     }
30     int findKthLargest(vector<int>& nums, int k) {
31         if (k < nums.size() / 2) {
32             return findKlarge(nums, k);
33         }
34         return findKsmall(nums, nums.size() - k + 1);
35     }
36 };

 

posted @ 2020-04-11 19:21  bloglxc  阅读(166)  评论(0编辑  收藏  举报