From c74d8162403b8c2e98031da66bdece3597f54477 Mon Sep 17 00:00:00 2001 From: rain84 Date: Sat, 29 Jun 2024 22:14:34 +0300 Subject: [PATCH 01/25] feat: add ts solution to lc problem: No.0215 --- .../README.md | 26 +++++++++++++++++++ .../README_EN.md | 26 +++++++++++++++++++ .../Solution3.ts | 11 ++++++++ 3 files changed, 63 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md index 88319b5d53771..8c40472967f2a 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md @@ -309,4 +309,30 @@ impl Solution { + + +### Solution 3: Max priority heap + + + +#### TypeScript + +```ts +function findKthLargest(nums: number[], k: number): number { + const maxPQ = new MaxPriorityQueue(); + for (const x of nums) { + maxPQ.enqueue(x); + } + + let res = 0; + while (k--) res = maxPQ.dequeue().element; + + return res; +} +``` + + + + + diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md index 0c7baa96018a3..7db04a21c7b6e 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md @@ -301,4 +301,30 @@ impl Solution { + + +### Solution 3: Max priority heap + + + +#### TypeScript + +```ts +function findKthLargest(nums: number[], k: number): number { + const maxPQ = new MaxPriorityQueue(); + for (const x of nums) { + maxPQ.enqueue(x); + } + + let res = 0; + while (k--) res = maxPQ.dequeue().element; + + return res; +} +``` + + + + + diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts new file mode 100644 index 0000000000000..479e2ed85bb4f --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts @@ -0,0 +1,11 @@ +function findKthLargest(nums: number[], k: number): number { + const maxPQ = new MaxPriorityQueue(); + for (const x of nums) { + maxPQ.enqueue(x); + } + + let res = 0; + while (k--) res = maxPQ.dequeue().element; + + return res; +} From 5967643be8d7d952a1ce137bcbf1f3cd778fef4f Mon Sep 17 00:00:00 2001 From: rain84 Date: Sat, 29 Jun 2024 22:40:36 +0300 Subject: [PATCH 02/25] feat: add ts solution to lc problem: No.0215 --- .../README.md | 32 +++++++++++++++++ .../README_EN.md | 34 +++++++++++++++++++ .../Solution4.ts | 17 ++++++++++ 3 files changed, 83 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md index 8c40472967f2a..2493205f11363 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md @@ -335,4 +335,36 @@ function findKthLargest(nums: number[], k: number): number { + + +### Solution 4: Hash + counting + + + +#### TypeScript + +```ts +function findKthLargest(nums: number[], k: number): number { + const n = 10 ** 4; + const length = n * 2 + 1; + const cnt = Array(length); + + for (const x of nums) { + cnt[x + n] = (cnt[x + n] ?? 0) + 1; + } + + for (let i = length; i >= 0; i--) { + if (!cnt[i]) continue; + k -= cnt[i]; + if (k <= 0) return i - n; + } + + return -1; +} +``` + + + + + diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md index 7db04a21c7b6e..433ca6049ce2c 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md @@ -327,4 +327,38 @@ function findKthLargest(nums: number[], k: number): number { + + + + +### Solution 4: Hash + counting + + + +#### TypeScript + +```ts +function findKthLargest(nums: number[], k: number): number { + const n = 10 ** 4; + const length = n * 2 + 1; + const cnt = Array(length); + + for (const x of nums) { + cnt[x + n] = (cnt[x + n] ?? 0) + 1; + } + + for (let i = length; i >= 0; i--) { + if (!cnt[i]) continue; + k -= cnt[i]; + if (k <= 0) return i - n; + } + + return -1; +} +``` + + + + + diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts new file mode 100644 index 0000000000000..ccd6994ff731f --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts @@ -0,0 +1,17 @@ +function findKthLargest(nums: number[], k: number): number { + const n = 10 ** 4; + const length = n * 2 + 1; + const cnt = Array(length); + + for (const x of nums) { + cnt[x + n] = (cnt[x + n] ?? 0) + 1; + } + + for (let i = length; i >= 0; i--) { + if (!cnt[i]) continue; + k -= cnt[i]; + if (k <= 0) return i - n; + } + + return -1; +} From afbe09e468415fef7511b879fdbd5ed2d043f794 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:50:52 +0800 Subject: [PATCH 03/25] Update README.md --- .../README.md | 484 ++++++++++++------ 1 file changed, 326 insertions(+), 158 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md index 2493205f11363..25600d881524f 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md @@ -56,11 +56,11 @@ tags: -### 方法一:排序 +### 方法一:快速选择 -我们可以将数组 $nums$ 升序排列,然后获取 $nums[n-k]$。 +快速选择算法是一种在未排序的数组中查找第 `k` 个最大元素或最小元素的算法。它的基本思想是每次选择一个基准元素,将数组分为两部分,一部分的元素都比基准元素小,另一部分的元素都比基准元素大,然后根据基准元素的位置,决定继续在左边还是右边查找,直到找到第 `k` 个最大元素。 -时间复杂度 $O(n \times \log n)$,其中 $n$ 表示数组 $nums$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中,$n$ 为数组 $\text{nums}$ 的长度。 @@ -69,11 +69,11 @@ tags: ```python class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: - def quick_sort(left, right, k): - if left == right: - return nums[left] - i, j = left - 1, right + 1 - x = nums[(left + right) >> 1] + def quick_sort(l: int, r: int) -> int: + if l == r: + return nums[l] + i, j = l - 1, r + 1 + x = nums[(l + r) >> 1] while i < j: while 1: i += 1 @@ -86,33 +86,38 @@ class Solution: if i < j: nums[i], nums[j] = nums[j], nums[i] if j < k: - return quick_sort(j + 1, right, k) - return quick_sort(left, j, k) + return quick_sort(j + 1, r) + return quick_sort(l, j) n = len(nums) - return quick_sort(0, n - 1, n - k) + k = n - k + return quick_sort(0, n - 1) ``` #### Java ```java class Solution { + private int[] nums; + private int k; + public int findKthLargest(int[] nums, int k) { - int n = nums.length; - return quickSort(nums, 0, n - 1, n - k); + this.nums = nums; + this.k = nums.length - k; + return quickSort(0, nums.length - 1); } - private int quickSort(int[] nums, int left, int right, int k) { - if (left == right) { - return nums[left]; + private int quickSort(int l, int r) { + if (l == r) { + return nums[l]; } - int i = left - 1, j = right + 1; - int x = nums[(left + right) >>> 1]; + int i = l - 1, j = r + 1; + int x = nums[(l + r) >>> 1]; while (i < j) { - while (nums[++i] < x) - ; - while (nums[--j] > x) - ; + while (nums[++i] < x) { + } + while (nums[--j] > x) { + } if (i < j) { int t = nums[i]; nums[i] = nums[j]; @@ -120,9 +125,9 @@ class Solution { } } if (j < k) { - return quickSort(nums, j + 1, right, k); + return quickSort(j + 1, r); } - return quickSort(nums, left, j, k); + return quickSort(l, j); } } ``` @@ -134,21 +139,28 @@ class Solution { public: int findKthLargest(vector& nums, int k) { int n = nums.size(); - return quickSort(nums, 0, n - 1, n - k); - } - - int quickSort(vector& nums, int left, int right, int k) { - if (left == right) return nums[left]; - int i = left - 1, j = right + 1; - int x = nums[left + right >> 1]; - while (i < j) { - while (nums[++i] < x) - ; - while (nums[--j] > x) - ; - if (i < j) swap(nums[i], nums[j]); - } - return j < k ? quickSort(nums, j + 1, right, k) : quickSort(nums, left, j, k); + k = n - k; + auto quickSort = [&](auto&& quickSort, int l, int r) -> int { + if (l == r) { + return nums[l]; + } + int i = l - 1, j = r + 1; + int x = nums[(l + r) >> 1]; + while (i < j) { + while (nums[++i] < x) { + } + while (nums[--j] > x) { + } + if (i < j) { + swap(nums[i], nums[j]); + } + } + if (j < k) { + return quickSort(quickSort, j + 1, r); + } + return quickSort(quickSort, l, j); + }; + return quickSort(quickSort, 0, n - 1); } }; ``` @@ -157,37 +169,37 @@ public: ```go func findKthLargest(nums []int, k int) int { - n := len(nums) - return quickSort(nums, 0, n-1, n-k) -} - -func quickSort(nums []int, left, right, k int) int { - if left == right { - return nums[left] - } - i, j := left-1, right+1 - x := nums[(left+right)>>1] - for i < j { - for { - i++ - if nums[i] >= x { - break - } + k = len(nums) - k + var quickSort func(l, r int) int + quickSort = func(l, r int) int { + if l == r { + return nums[l] } - for { - j-- - if nums[j] <= x { - break + i, j := l-1, r+1 + x := nums[(l+r)>>1] + for i < j { + for { + i++ + if nums[i] >= x { + break + } + } + for { + j-- + if nums[j] <= x { + break + } + } + if i < j { + nums[i], nums[j] = nums[j], nums[i] } } - if i < j { - nums[i], nums[j] = nums[j], nums[i] + if j < k { + return quickSort(j+1, r) } + return quickSort(l, j) } - if j < k { - return quickSort(nums, j+1, right, k) - } - return quickSort(nums, left, j, k) + return quickSort(0, len(nums)-1) } ``` @@ -196,62 +208,69 @@ func quickSort(nums []int, left, right, k int) int { ```ts function findKthLargest(nums: number[], k: number): number { const n = nums.length; - const swap = (i: number, j: number) => { - [nums[i], nums[j]] = [nums[j], nums[i]]; - }; - const sort = (l: number, r: number) => { - if (l + 1 > k || l >= r) { - return; + k = n - k; + const quickSort = (l: number, r: number): number => { + if (l === r) { + return nums[l]; } - swap(l, l + Math.floor(Math.random() * (r - l))); - const num = nums[l]; - let mark = l; - for (let i = l + 1; i < r; i++) { - if (nums[i] > num) { - mark++; - swap(i, mark); + let [i, j] = [l - 1, r + 1]; + const x = nums[(l + r) >> 1]; + while (i < j) { + while (nums[++i] < x); + while (nums[--j] > x); + if (i < j) { + [nums[i], nums[j]] = [nums[j], nums[i]]; } } - swap(l, mark); - - sort(l, mark); - sort(mark + 1, r); + if (j < k) { + return quickSort(j + 1, r); + } + return quickSort(l, j); }; - sort(0, n); - return nums[k - 1]; + return quickSort(0, n - 1); } ``` #### Rust ```rust -use rand::Rng; - impl Solution { - fn sort(nums: &mut Vec, l: usize, r: usize, k: usize) { - if l + 1 > k || l >= r { - return; + pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { + let len = nums.len(); + let k = len - k as usize; + Self::quick_sort(&mut nums, 0, len - 1, k) + } + + fn quick_sort(nums: &mut Vec, l: usize, r: usize, k: usize) -> i32 { + if l == r { + return nums[l]; } - nums.swap(l, rand::thread_rng().gen_range(l, r)); - let num = nums[l]; - let mut mark = l; - for i in l..r { - if nums[i] > num { - mark += 1; - nums.swap(i, mark); + + let (mut i, mut j) = (l as isize - 1, r as isize + 1); + let x = nums[(l + r) / 2]; + + while i < j { + i += 1; + while nums[i as usize] < x { + i += 1; } - } - nums.swap(l, mark); - Self::sort(nums, l, mark, k); - Self::sort(nums, mark + 1, r, k); - } + j -= 1; + while nums[j as usize] > x { + j -= 1; + } - pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { - let n = nums.len(); - let k = k as usize; - Self::sort(&mut nums, 0, n, k); - nums[k - 1] + if i < j { + nums.swap(i as usize, j as usize); + } + } + + let j = j as usize; + if j < k { + Self::quick_sort(nums, j + 1, r, k) + } else { + Self::quick_sort(nums, l, j, k) + } } } ``` @@ -262,72 +281,114 @@ impl Solution { -### 方法二:Partition - -我们注意到,并不是所有时候,都需要整个数组进入有序状态,只需要**局部有序**,或者说,从大到小排序,只要 $[0..k)$ 位置的元素有序,那么就能确定结果,此处使用**快速排序**。 +### 方法二:优先队列(小根堆) -快速排序有一特点,每一次循环结束时,能够确定的是 $partition$ 一定处于它该处于的索引位置。从而根据它得知,结果值是在左数组还是在右数组当中,然后对那一数组进行排序即可。 +我们可以维护一个大小为 $k$ 的小根堆 $\text{minQ}$,然后遍历数组 $\text{nums}$,将数组中的元素依次加入到小根堆中,当小根堆的大小超过 $k$ 时,我们将堆顶元素弹出,这样最终小根堆中的 $k$ 个元素就是数组中的 $k$ 个最大元素,堆顶元素就是第 $k$ 个最大元素。 -时间复杂度 $O(n)$,其中 $n$ 表示数组 $nums$ 的长度。 +时间复杂度 $O(n\log k)$,空间复杂度 $O(k)$。其中,$n$ 为数组 $\text{nums}$ 的长度。 -#### Rust +#### Python3 -```rust -use rand::Rng; +```python +class Solution: + def findKthLargest(self, nums: List[int], k: int) -> int: + return nlargest(k, nums)[-1] +``` -impl Solution { - pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { - let k = k as usize; - let n = nums.len(); - let mut l = 0; - let mut r = n; - while l <= k - 1 && l < r { - nums.swap(l, rand::thread_rng().gen_range(l, r)); - let num = nums[l]; - let mut mark = l; - for i in l..r { - if nums[i] > num { - mark += 1; - nums.swap(i, mark); - } - } - nums.swap(l, mark); - if mark + 1 <= k { - l = mark + 1; - } else { - r = mark; +#### Java + +```java +class Solution { + public int findKthLargest(int[] nums, int k) { + PriorityQueue minQ = new PriorityQueue<>(); + for (int x : nums) { + minQ.offer(x); + if (minQ.size() > k) { + minQ.poll(); } } - nums[k - 1] + return minQ.peek(); } } ``` - +#### C++ - +```cpp +class Solution { +public: + int findKthLargest(vector& nums, int k) { + priority_queue, greater> minQ; + for (int x : nums) { + minQ.push(x); + if (minQ.size() > k) { + minQ.pop(); + } + } + return minQ.top(); + } +}; +``` - +#### Go -### Solution 3: Max priority heap +```go +func findKthLargest(nums []int, k int) int { + minQ := hp{} + for _, x := range nums { + heap.Push(&minQ, x) + if minQ.Len() > k { + heap.Pop(&minQ) + } + } + return minQ.IntSlice[0] +} - +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] } +func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) } +func (h *hp) Pop() any { + a := h.IntSlice + v := a[len(a)-1] + h.IntSlice = a[:len(a)-1] + return v +} +``` #### TypeScript ```ts function findKthLargest(nums: number[], k: number): number { - const maxPQ = new MaxPriorityQueue(); + const minQ = new MinPriorityQueue(); for (const x of nums) { - maxPQ.enqueue(x); + minQ.enqueue(x); + if (minQ.size() > k) { + minQ.dequeue(); + } } + return minQ.front().element; +} +``` - let res = 0; - while (k--) res = maxPQ.dequeue().element; +#### Rust - return res; +```rust +use std::collections::BinaryHeap; + +impl Solution { + pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { + let mut minQ = BinaryHeap::new(); + for &x in nums.iter() { + minQ.push(-x); + if minQ.len() > k as usize { + minQ.pop(); + } + } + -minQ.peek().unwrap() + } } ``` @@ -337,29 +398,136 @@ function findKthLargest(nums: number[], k: number): number { -### Solution 4: Hash + counting +### 方法三:计数排序 + +我们可以使用计数排序的思想,统计数组 $\text{nums}$ 中每个元素出现的次数,记录在哈希表 $\text{cnt}$ 中,然后从大到小遍历元素 $i$,每次减去出现的次数 $\text{cnt}[i]$,直到 $k$ 小于等于 $0$,此时的元素 $i$ 就是数组中的第 $k$ 个最大元素。 + +时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $\text{nums}$ 的长度,而 $m$ 为数组 $\text{nums}$ 中元素的最大值。 +#### Python3 + +```python +class Solution: + def findKthLargest(self, nums: List[int], k: int) -> int: + cnt = Counter(nums) + for i in count(max(cnt), -1): + k -= cnt[i] + if k <= 0: + return i +``` + +#### Java + +```java +class Solution { + public int findKthLargest(int[] nums, int k) { + Map cnt = new HashMap<>(nums.length); + int m = Integer.MIN_VALUE; + for (int x : nums) { + m = Math.max(m, x); + cnt.merge(x, 1, Integer::sum); + } + for (int i = m;; --i) { + k -= cnt.getOrDefault(i, 0); + if (k <= 0) { + return i; + } + } + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int findKthLargest(vector& nums, int k) { + unordered_map cnt; + int m = INT_MIN; + for (int x : nums) { + ++cnt[x]; + m = max(m, x); + } + for (int i = m;; --i) { + k -= cnt[i]; + if (k <= 0) { + return i; + } + } + } +}; +``` + +#### Go + +```go +func findKthLargest(nums []int, k int) int { + cnt := map[int]int{} + m := -(1 << 30) + for _, x := range nums { + cnt[x]++ + m = max(m, x) + } + for i := m; ; i-- { + k -= cnt[i] + if k <= 0 { + return i + } + } + +} +``` + #### TypeScript ```ts function findKthLargest(nums: number[], k: number): number { - const n = 10 ** 4; - const length = n * 2 + 1; - const cnt = Array(length); - + const cnt: Record = {}; for (const x of nums) { - cnt[x + n] = (cnt[x + n] ?? 0) + 1; + cnt[x] = (cnt[x] || 0) + 1; } - - for (let i = length; i >= 0; i--) { - if (!cnt[i]) continue; - k -= cnt[i]; - if (k <= 0) return i - n; + const m = Math.max(...nums); + for (let i = m; ; --i) { + k -= cnt[i] || 0; + if (k <= 0) { + return i; + } } +} +``` + +#### Rust + +```rust +use std::collections::HashMap; - return -1; +impl Solution { + pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { + let mut cnt = HashMap::new(); + let mut m = i32::MIN; + + for &x in &nums { + *cnt.entry(x).or_insert(0) += 1; + if x > m { + m = x; + } + } + + let mut k = k; + for i in (i32::MIN..=m).rev() { + if let Some(&count) = cnt.get(&i) { + k -= count; + if k <= 0 { + return i; + } + } + } + + unreachable!(); + } } ``` From 834acf8499ceb4ebf3ccf41d7a9468cfa7e9f233 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:51:25 +0800 Subject: [PATCH 04/25] Update README.md --- .../0200-0299/0215.Kth Largest Element in an Array/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md index 25600d881524f..c38a44c965194 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README.md @@ -60,7 +60,7 @@ tags: 快速选择算法是一种在未排序的数组中查找第 `k` 个最大元素或最小元素的算法。它的基本思想是每次选择一个基准元素,将数组分为两部分,一部分的元素都比基准元素小,另一部分的元素都比基准元素大,然后根据基准元素的位置,决定继续在左边还是右边查找,直到找到第 `k` 个最大元素。 -时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中,$n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 @@ -285,7 +285,7 @@ impl Solution { 我们可以维护一个大小为 $k$ 的小根堆 $\text{minQ}$,然后遍历数组 $\text{nums}$,将数组中的元素依次加入到小根堆中,当小根堆的大小超过 $k$ 时,我们将堆顶元素弹出,这样最终小根堆中的 $k$ 个元素就是数组中的 $k$ 个最大元素,堆顶元素就是第 $k$ 个最大元素。 -时间复杂度 $O(n\log k)$,空间复杂度 $O(k)$。其中,$n$ 为数组 $\text{nums}$ 的长度。 +时间复杂度 $O(n\log k)$,空间复杂度 $O(k)$。其中 $n$ 为数组 $\text{nums}$ 的长度。 From 50a23fc3ad586f548e55ce902765056d5d9a6b31 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:51:36 +0800 Subject: [PATCH 05/25] Update README_EN.md --- .../README_EN.md | 486 ++++++++++++------ 1 file changed, 326 insertions(+), 160 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md index 433ca6049ce2c..9eecbd3277365 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/README_EN.md @@ -48,11 +48,11 @@ tags: -### Solution 1: Sorting +### Solution 1: Quick Select -We can sort the array $nums$ in ascending order, and then get $nums[n-k]$. +Quick Select is an algorithm for finding the $k^{th}$ largest or smallest element in an unsorted array. Its basic idea is to select a pivot element each time, dividing the array into two parts: one part contains elements smaller than the pivot, and the other part contains elements larger than the pivot. Then, based on the position of the pivot, it decides whether to continue the search on the left or right side until the $k^{th}$ largest element is found. -The time complexity is $O(n \times \log n)$, where $n$ is the length of the array $nums$. +The time complexity is $O(n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\text{nums}$. @@ -61,11 +61,11 @@ The time complexity is $O(n \times \log n)$, where $n$ is the length of the arra ```python class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: - def quick_sort(left, right, k): - if left == right: - return nums[left] - i, j = left - 1, right + 1 - x = nums[(left + right) >> 1] + def quick_sort(l: int, r: int) -> int: + if l == r: + return nums[l] + i, j = l - 1, r + 1 + x = nums[(l + r) >> 1] while i < j: while 1: i += 1 @@ -78,33 +78,38 @@ class Solution: if i < j: nums[i], nums[j] = nums[j], nums[i] if j < k: - return quick_sort(j + 1, right, k) - return quick_sort(left, j, k) + return quick_sort(j + 1, r) + return quick_sort(l, j) n = len(nums) - return quick_sort(0, n - 1, n - k) + k = n - k + return quick_sort(0, n - 1) ``` #### Java ```java class Solution { + private int[] nums; + private int k; + public int findKthLargest(int[] nums, int k) { - int n = nums.length; - return quickSort(nums, 0, n - 1, n - k); + this.nums = nums; + this.k = nums.length - k; + return quickSort(0, nums.length - 1); } - private int quickSort(int[] nums, int left, int right, int k) { - if (left == right) { - return nums[left]; + private int quickSort(int l, int r) { + if (l == r) { + return nums[l]; } - int i = left - 1, j = right + 1; - int x = nums[(left + right) >>> 1]; + int i = l - 1, j = r + 1; + int x = nums[(l + r) >>> 1]; while (i < j) { - while (nums[++i] < x) - ; - while (nums[--j] > x) - ; + while (nums[++i] < x) { + } + while (nums[--j] > x) { + } if (i < j) { int t = nums[i]; nums[i] = nums[j]; @@ -112,9 +117,9 @@ class Solution { } } if (j < k) { - return quickSort(nums, j + 1, right, k); + return quickSort(j + 1, r); } - return quickSort(nums, left, j, k); + return quickSort(l, j); } } ``` @@ -126,21 +131,28 @@ class Solution { public: int findKthLargest(vector& nums, int k) { int n = nums.size(); - return quickSort(nums, 0, n - 1, n - k); - } - - int quickSort(vector& nums, int left, int right, int k) { - if (left == right) return nums[left]; - int i = left - 1, j = right + 1; - int x = nums[left + right >> 1]; - while (i < j) { - while (nums[++i] < x) - ; - while (nums[--j] > x) - ; - if (i < j) swap(nums[i], nums[j]); - } - return j < k ? quickSort(nums, j + 1, right, k) : quickSort(nums, left, j, k); + k = n - k; + auto quickSort = [&](auto&& quickSort, int l, int r) -> int { + if (l == r) { + return nums[l]; + } + int i = l - 1, j = r + 1; + int x = nums[(l + r) >> 1]; + while (i < j) { + while (nums[++i] < x) { + } + while (nums[--j] > x) { + } + if (i < j) { + swap(nums[i], nums[j]); + } + } + if (j < k) { + return quickSort(quickSort, j + 1, r); + } + return quickSort(quickSort, l, j); + }; + return quickSort(quickSort, 0, n - 1); } }; ``` @@ -149,37 +161,37 @@ public: ```go func findKthLargest(nums []int, k int) int { - n := len(nums) - return quickSort(nums, 0, n-1, n-k) -} - -func quickSort(nums []int, left, right, k int) int { - if left == right { - return nums[left] - } - i, j := left-1, right+1 - x := nums[(left+right)>>1] - for i < j { - for { - i++ - if nums[i] >= x { - break - } + k = len(nums) - k + var quickSort func(l, r int) int + quickSort = func(l, r int) int { + if l == r { + return nums[l] } - for { - j-- - if nums[j] <= x { - break + i, j := l-1, r+1 + x := nums[(l+r)>>1] + for i < j { + for { + i++ + if nums[i] >= x { + break + } + } + for { + j-- + if nums[j] <= x { + break + } + } + if i < j { + nums[i], nums[j] = nums[j], nums[i] } } - if i < j { - nums[i], nums[j] = nums[j], nums[i] + if j < k { + return quickSort(j+1, r) } + return quickSort(l, j) } - if j < k { - return quickSort(nums, j+1, right, k) - } - return quickSort(nums, left, j, k) + return quickSort(0, len(nums)-1) } ``` @@ -188,62 +200,69 @@ func quickSort(nums []int, left, right, k int) int { ```ts function findKthLargest(nums: number[], k: number): number { const n = nums.length; - const swap = (i: number, j: number) => { - [nums[i], nums[j]] = [nums[j], nums[i]]; - }; - const sort = (l: number, r: number) => { - if (l + 1 > k || l >= r) { - return; + k = n - k; + const quickSort = (l: number, r: number): number => { + if (l === r) { + return nums[l]; } - swap(l, l + Math.floor(Math.random() * (r - l))); - const num = nums[l]; - let mark = l; - for (let i = l + 1; i < r; i++) { - if (nums[i] > num) { - mark++; - swap(i, mark); + let [i, j] = [l - 1, r + 1]; + const x = nums[(l + r) >> 1]; + while (i < j) { + while (nums[++i] < x); + while (nums[--j] > x); + if (i < j) { + [nums[i], nums[j]] = [nums[j], nums[i]]; } } - swap(l, mark); - - sort(l, mark); - sort(mark + 1, r); + if (j < k) { + return quickSort(j + 1, r); + } + return quickSort(l, j); }; - sort(0, n); - return nums[k - 1]; + return quickSort(0, n - 1); } ``` #### Rust ```rust -use rand::Rng; - impl Solution { - fn sort(nums: &mut Vec, l: usize, r: usize, k: usize) { - if l + 1 > k || l >= r { - return; + pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { + let len = nums.len(); + let k = len - k as usize; + Self::quick_sort(&mut nums, 0, len - 1, k) + } + + fn quick_sort(nums: &mut Vec, l: usize, r: usize, k: usize) -> i32 { + if l == r { + return nums[l]; } - nums.swap(l, rand::thread_rng().gen_range(l, r)); - let num = nums[l]; - let mut mark = l; - for i in l..r { - if nums[i] > num { - mark += 1; - nums.swap(i, mark); + + let (mut i, mut j) = (l as isize - 1, r as isize + 1); + let x = nums[(l + r) / 2]; + + while i < j { + i += 1; + while nums[i as usize] < x { + i += 1; } - } - nums.swap(l, mark); - Self::sort(nums, l, mark, k); - Self::sort(nums, mark + 1, r, k); - } + j -= 1; + while nums[j as usize] > x { + j -= 1; + } - pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { - let n = nums.len(); - let k = k as usize; - Self::sort(&mut nums, 0, n, k); - nums[k - 1] + if i < j { + nums.swap(i as usize, j as usize); + } + } + + let j = j as usize; + if j < k { + Self::quick_sort(nums, j + 1, r, k) + } else { + Self::quick_sort(nums, l, j, k) + } } } ``` @@ -254,72 +273,114 @@ impl Solution { -### Solution 2: Partition - -We notice that it is not always necessary for the entire array to be in an ordered state. We only need **local order**. That is to say, if the elements in the position $[0..k)$ are sorted in descending order, then we can determine the result. Here we use **quick sort**. +### Solution 2: Priority Queue (Min Heap) -Quick sort has a characteristic that at the end of each loop, it can be determined that the $partition$ is definitely at the index position it should be. Therefore, based on it, we know whether the result value is in the left array or in the right array, and then sort that array. +We can maintain a min heap $\text{minQ}$ of size $k$, and then iterate through the array $\text{nums}$, adding each element to the min heap. When the size of the min heap exceeds $k$, we pop the top element of the heap. This way, the final $k$ elements in the min heap are the $k$ largest elements in the array, and the top element of the heap is the $k^{th}$ largest element. -The time complexity is $O(n)$, where $n$ is the length of the array $nums$. +The time complexity is $O(n\log k)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array $\text{nums}$. -#### Rust +#### Python3 -```rust -use rand::Rng; +```python +class Solution: + def findKthLargest(self, nums: List[int], k: int) -> int: + return nlargest(k, nums)[-1] +``` -impl Solution { - pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { - let k = k as usize; - let n = nums.len(); - let mut l = 0; - let mut r = n; - while l <= k - 1 && l < r { - nums.swap(l, rand::thread_rng().gen_range(l, r)); - let num = nums[l]; - let mut mark = l; - for i in l..r { - if nums[i] > num { - mark += 1; - nums.swap(i, mark); - } - } - nums.swap(l, mark); - if mark + 1 <= k { - l = mark + 1; - } else { - r = mark; +#### Java + +```java +class Solution { + public int findKthLargest(int[] nums, int k) { + PriorityQueue minQ = new PriorityQueue<>(); + for (int x : nums) { + minQ.offer(x); + if (minQ.size() > k) { + minQ.poll(); } } - nums[k - 1] + return minQ.peek(); } } ``` - +#### C++ - +```cpp +class Solution { +public: + int findKthLargest(vector& nums, int k) { + priority_queue, greater> minQ; + for (int x : nums) { + minQ.push(x); + if (minQ.size() > k) { + minQ.pop(); + } + } + return minQ.top(); + } +}; +``` - +#### Go -### Solution 3: Max priority heap +```go +func findKthLargest(nums []int, k int) int { + minQ := hp{} + for _, x := range nums { + heap.Push(&minQ, x) + if minQ.Len() > k { + heap.Pop(&minQ) + } + } + return minQ.IntSlice[0] +} - +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] } +func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) } +func (h *hp) Pop() any { + a := h.IntSlice + v := a[len(a)-1] + h.IntSlice = a[:len(a)-1] + return v +} +``` #### TypeScript ```ts function findKthLargest(nums: number[], k: number): number { - const maxPQ = new MaxPriorityQueue(); + const minQ = new MinPriorityQueue(); for (const x of nums) { - maxPQ.enqueue(x); + minQ.enqueue(x); + if (minQ.size() > k) { + minQ.dequeue(); + } } + return minQ.front().element; +} +``` - let res = 0; - while (k--) res = maxPQ.dequeue().element; +#### Rust + +```rust +use std::collections::BinaryHeap; - return res; +impl Solution { + pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { + let mut minQ = BinaryHeap::new(); + for &x in nums.iter() { + minQ.push(-x); + if minQ.len() > k as usize { + minQ.pop(); + } + } + -minQ.peek().unwrap() + } } ``` @@ -327,33 +388,138 @@ function findKthLargest(nums: number[], k: number): number { - - -### Solution 4: Hash + counting +### Solution 3: Counting Sort + +We can use the idea of counting sort, counting the occurrence of each element in the array $\text{nums}$ and recording it in a hash table $\text{cnt}$. Then, we iterate over the elements $i$ from largest to smallest, subtracting the occurrence count $\text{cnt}[i]$ each time, until $k$ is less than or equal to $0$. At this point, the element $i$ is the $k^{th}$ largest element in the array. + +The time complexity is $O(n + m)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $\text{nums}$, and $m$ is the maximum value among the elements in $\text{nums}$. +#### Python3 + +```python +class Solution: + def findKthLargest(self, nums: List[int], k: int) -> int: + cnt = Counter(nums) + for i in count(max(cnt), -1): + k -= cnt[i] + if k <= 0: + return i +``` + +#### Java + +```java +class Solution { + public int findKthLargest(int[] nums, int k) { + Map cnt = new HashMap<>(nums.length); + int m = Integer.MIN_VALUE; + for (int x : nums) { + m = Math.max(m, x); + cnt.merge(x, 1, Integer::sum); + } + for (int i = m;; --i) { + k -= cnt.getOrDefault(i, 0); + if (k <= 0) { + return i; + } + } + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + int findKthLargest(vector& nums, int k) { + unordered_map cnt; + int m = INT_MIN; + for (int x : nums) { + ++cnt[x]; + m = max(m, x); + } + for (int i = m;; --i) { + k -= cnt[i]; + if (k <= 0) { + return i; + } + } + } +}; +``` + +#### Go + +```go +func findKthLargest(nums []int, k int) int { + cnt := map[int]int{} + m := -(1 << 30) + for _, x := range nums { + cnt[x]++ + m = max(m, x) + } + for i := m; ; i-- { + k -= cnt[i] + if k <= 0 { + return i + } + } + +} +``` + #### TypeScript ```ts function findKthLargest(nums: number[], k: number): number { - const n = 10 ** 4; - const length = n * 2 + 1; - const cnt = Array(length); - + const cnt: Record = {}; for (const x of nums) { - cnt[x + n] = (cnt[x + n] ?? 0) + 1; + cnt[x] = (cnt[x] || 0) + 1; } - - for (let i = length; i >= 0; i--) { - if (!cnt[i]) continue; - k -= cnt[i]; - if (k <= 0) return i - n; + const m = Math.max(...nums); + for (let i = m; ; --i) { + k -= cnt[i] || 0; + if (k <= 0) { + return i; + } } +} +``` + +#### Rust + +```rust +use std::collections::HashMap; - return -1; +impl Solution { + pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { + let mut cnt = HashMap::new(); + let mut m = i32::MIN; + + for &x in &nums { + *cnt.entry(x).or_insert(0) += 1; + if x > m { + m = x; + } + } + + let mut k = k; + for i in (i32::MIN..=m).rev() { + if let Some(&count) = cnt.get(&i) { + k -= count; + if k <= 0 { + return i; + } + } + } + + unreachable!(); + } } ``` From 1a0b3e3b1b529678a34fe97997c2699145720553 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:52:23 +0800 Subject: [PATCH 06/25] Update Solution.py --- .../Solution.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.py b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.py index aeb737a82fa7b..b27d2a78ab1b8 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.py +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.py @@ -1,10 +1,10 @@ class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: - def quick_sort(left, right, k): - if left == right: - return nums[left] - i, j = left - 1, right + 1 - x = nums[(left + right) >> 1] + def quick_sort(l: int, r: int) -> int: + if l == r: + return nums[l] + i, j = l - 1, r + 1 + x = nums[(l + r) >> 1] while i < j: while 1: i += 1 @@ -17,8 +17,9 @@ def quick_sort(left, right, k): if i < j: nums[i], nums[j] = nums[j], nums[i] if j < k: - return quick_sort(j + 1, right, k) - return quick_sort(left, j, k) + return quick_sort(j + 1, r) + return quick_sort(l, j) n = len(nums) - return quick_sort(0, n - 1, n - k) + k = n - k + return quick_sort(0, n - 1) From ff0882cfd74675110a96dc5843de3747886e1ea7 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:52:32 +0800 Subject: [PATCH 07/25] Update Solution.java --- .../Solution.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.java b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.java index 7495f50a604f4..5cddc984a4df1 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.java +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.java @@ -1,20 +1,24 @@ class Solution { + private int[] nums; + private int k; + public int findKthLargest(int[] nums, int k) { - int n = nums.length; - return quickSort(nums, 0, n - 1, n - k); + this.nums = nums; + this.k = nums.length - k; + return quickSort(0, nums.length - 1); } - private int quickSort(int[] nums, int left, int right, int k) { - if (left == right) { - return nums[left]; + private int quickSort(int l, int r) { + if (l == r) { + return nums[l]; } - int i = left - 1, j = right + 1; - int x = nums[(left + right) >>> 1]; + int i = l - 1, j = r + 1; + int x = nums[(l + r) >>> 1]; while (i < j) { - while (nums[++i] < x) - ; - while (nums[--j] > x) - ; + while (nums[++i] < x) { + } + while (nums[--j] > x) { + } if (i < j) { int t = nums[i]; nums[i] = nums[j]; @@ -22,8 +26,8 @@ private int quickSort(int[] nums, int left, int right, int k) { } } if (j < k) { - return quickSort(nums, j + 1, right, k); + return quickSort(j + 1, r); } - return quickSort(nums, left, j, k); + return quickSort(l, j); } -} \ No newline at end of file +} From 76dd4eb01e59ea0a9174bdc5ab67673ab629bb0f Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:52:42 +0800 Subject: [PATCH 08/25] Update Solution.cpp --- .../Solution.cpp | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.cpp b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.cpp index 9413e80e60e65..c94e6e71cb076 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.cpp +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.cpp @@ -2,20 +2,27 @@ class Solution { public: int findKthLargest(vector& nums, int k) { int n = nums.size(); - return quickSort(nums, 0, n - 1, n - k); + k = n - k; + auto quickSort = [&](auto&& quickSort, int l, int r) -> int { + if (l == r) { + return nums[l]; + } + int i = l - 1, j = r + 1; + int x = nums[(l + r) >> 1]; + while (i < j) { + while (nums[++i] < x) { + } + while (nums[--j] > x) { + } + if (i < j) { + swap(nums[i], nums[j]); + } + } + if (j < k) { + return quickSort(quickSort, j + 1, r); + } + return quickSort(quickSort, l, j); + }; + return quickSort(quickSort, 0, n - 1); } - - int quickSort(vector& nums, int left, int right, int k) { - if (left == right) return nums[left]; - int i = left - 1, j = right + 1; - int x = nums[left + right >> 1]; - while (i < j) { - while (nums[++i] < x) - ; - while (nums[--j] > x) - ; - if (i < j) swap(nums[i], nums[j]); - } - return j < k ? quickSort(nums, j + 1, right, k) : quickSort(nums, left, j, k); - } -}; \ No newline at end of file +}; From e1e587ed4326bf2171585d3c3e818b10ec8a6376 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:52:49 +0800 Subject: [PATCH 09/25] Update Solution.go --- .../Solution.go | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.go b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.go index c844d061abc28..11045a300cdba 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.go +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.go @@ -1,33 +1,33 @@ func findKthLargest(nums []int, k int) int { - n := len(nums) - return quickSort(nums, 0, n-1, n-k) -} - -func quickSort(nums []int, left, right, k int) int { - if left == right { - return nums[left] - } - i, j := left-1, right+1 - x := nums[(left+right)>>1] - for i < j { - for { - i++ - if nums[i] >= x { - break - } + k = len(nums) - k + var quickSort func(l, r int) int + quickSort = func(l, r int) int { + if l == r { + return nums[l] } - for { - j-- - if nums[j] <= x { - break + i, j := l-1, r+1 + x := nums[(l+r)>>1] + for i < j { + for { + i++ + if nums[i] >= x { + break + } + } + for { + j-- + if nums[j] <= x { + break + } + } + if i < j { + nums[i], nums[j] = nums[j], nums[i] } } - if i < j { - nums[i], nums[j] = nums[j], nums[i] + if j < k { + return quickSort(j+1, r) } + return quickSort(l, j) } - if j < k { - return quickSort(nums, j+1, right, k) - } - return quickSort(nums, left, j, k) -} \ No newline at end of file + return quickSort(0, len(nums)-1) +} From 1a4dfef7bad3ab7beccac465175c141e4b9ad3f0 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:52:58 +0800 Subject: [PATCH 10/25] Update Solution.ts --- .../Solution.ts | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.ts index 962a1dd6e9bcc..24f2304ff547b 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.ts +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.ts @@ -1,26 +1,23 @@ function findKthLargest(nums: number[], k: number): number { const n = nums.length; - const swap = (i: number, j: number) => { - [nums[i], nums[j]] = [nums[j], nums[i]]; - }; - const sort = (l: number, r: number) => { - if (l + 1 > k || l >= r) { - return; + k = n - k; + const quickSort = (l: number, r: number): number => { + if (l === r) { + return nums[l]; } - swap(l, l + Math.floor(Math.random() * (r - l))); - const num = nums[l]; - let mark = l; - for (let i = l + 1; i < r; i++) { - if (nums[i] > num) { - mark++; - swap(i, mark); + let [i, j] = [l - 1, r + 1]; + const x = nums[(l + r) >> 1]; + while (i < j) { + while (nums[++i] < x); + while (nums[--j] > x); + if (i < j) { + [nums[i], nums[j]] = [nums[j], nums[i]]; } } - swap(l, mark); - - sort(l, mark); - sort(mark + 1, r); + if (j < k) { + return quickSort(j + 1, r); + } + return quickSort(l, j); }; - sort(0, n); - return nums[k - 1]; + return quickSort(0, n - 1); } From f0785f54338b50afcbfbdeb2a42932b62a87e5df Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:53:08 +0800 Subject: [PATCH 11/25] Update Solution.rs --- .../Solution.rs | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.rs b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.rs index 1a47146d1dc77..343ac9b22ad14 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.rs +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution.rs @@ -1,29 +1,39 @@ -use rand::Rng; - impl Solution { - fn sort(nums: &mut Vec, l: usize, r: usize, k: usize) { - if l + 1 > k || l >= r { - return; + pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { + let len = nums.len(); + let k = len - k as usize; + Self::quick_sort(&mut nums, 0, len - 1, k) + } + + fn quick_sort(nums: &mut Vec, l: usize, r: usize, k: usize) -> i32 { + if l == r { + return nums[l]; } - nums.swap(l, rand::thread_rng().gen_range(l, r)); - let num = nums[l]; - let mut mark = l; - for i in l..r { - if nums[i] > num { - mark += 1; - nums.swap(i, mark); + + let (mut i, mut j) = (l as isize - 1, r as isize + 1); + let x = nums[(l + r) / 2]; + + while i < j { + i += 1; + while nums[i as usize] < x { + i += 1; } - } - nums.swap(l, mark); - Self::sort(nums, l, mark, k); - Self::sort(nums, mark + 1, r, k); - } + j -= 1; + while nums[j as usize] > x { + j -= 1; + } - pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { - let n = nums.len(); - let k = k as usize; - Self::sort(&mut nums, 0, n, k); - nums[k - 1] + if i < j { + nums.swap(i as usize, j as usize); + } + } + + let j = j as usize; + if j < k { + Self::quick_sort(nums, j + 1, r, k) + } else { + Self::quick_sort(nums, l, j, k) + } } } From 6b8b9fe310406170fb79b1b576d7cd46778e0cc1 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:53:23 +0800 Subject: [PATCH 12/25] Create Solution2.py --- .../0215.Kth Largest Element in an Array/Solution2.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.py diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.py b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.py new file mode 100644 index 0000000000000..3f1ed5fcc6abc --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.py @@ -0,0 +1,3 @@ +class Solution: + def findKthLargest(self, nums: List[int], k: int) -> int: + return nlargest(k, nums)[-1] From e4acc50c3fa5d77af4787318a0c3381dafb00e44 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:53:35 +0800 Subject: [PATCH 13/25] Create Solution2.java --- .../Solution2.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.java diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.java b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.java new file mode 100644 index 0000000000000..2d1263d894470 --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.java @@ -0,0 +1,12 @@ +class Solution { + public int findKthLargest(int[] nums, int k) { + PriorityQueue minQ = new PriorityQueue<>(); + for (int x : nums) { + minQ.offer(x); + if (minQ.size() > k) { + minQ.poll(); + } + } + return minQ.peek(); + } +} From 9c2a25c407c909a5383cc84a6fc3f069a74e4c81 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:53:48 +0800 Subject: [PATCH 14/25] Create Solution2.cpp --- .../Solution2.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.cpp diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.cpp b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.cpp new file mode 100644 index 0000000000000..7086e6d2abc43 --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.cpp @@ -0,0 +1,13 @@ +class Solution { +public: + int findKthLargest(vector& nums, int k) { + priority_queue, greater> minQ; + for (int x : nums) { + minQ.push(x); + if (minQ.size() > k) { + minQ.pop(); + } + } + return minQ.top(); + } +}; From 8a6c747cb746c5fdd6231ad4b1bc5f2ddb406cb3 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:53:59 +0800 Subject: [PATCH 15/25] Create Solution2.go --- .../Solution2.go | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.go diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.go b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.go new file mode 100644 index 0000000000000..c2a6e9e5fda93 --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.go @@ -0,0 +1,21 @@ +func findKthLargest(nums []int, k int) int { + minQ := hp{} + for _, x := range nums { + heap.Push(&minQ, x) + if minQ.Len() > k { + heap.Pop(&minQ) + } + } + return minQ.IntSlice[0] +} + +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] } +func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) } +func (h *hp) Pop() any { + a := h.IntSlice + v := a[len(a)-1] + h.IntSlice = a[:len(a)-1] + return v +} From b7824fe7b5f2d542e5be8ecc0a5644e7384e68a6 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:54:11 +0800 Subject: [PATCH 16/25] Delete solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts --- .../Solution4.ts | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts deleted file mode 100644 index ccd6994ff731f..0000000000000 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution4.ts +++ /dev/null @@ -1,17 +0,0 @@ -function findKthLargest(nums: number[], k: number): number { - const n = 10 ** 4; - const length = n * 2 + 1; - const cnt = Array(length); - - for (const x of nums) { - cnt[x + n] = (cnt[x + n] ?? 0) + 1; - } - - for (let i = length; i >= 0; i--) { - if (!cnt[i]) continue; - k -= cnt[i]; - if (k <= 0) return i - n; - } - - return -1; -} From aa23105bcb7f45dcf9ea2d021b83c09b3b2fc811 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:54:21 +0800 Subject: [PATCH 17/25] Delete solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts --- .../0215.Kth Largest Element in an Array/Solution3.ts | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts deleted file mode 100644 index 479e2ed85bb4f..0000000000000 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts +++ /dev/null @@ -1,11 +0,0 @@ -function findKthLargest(nums: number[], k: number): number { - const maxPQ = new MaxPriorityQueue(); - for (const x of nums) { - maxPQ.enqueue(x); - } - - let res = 0; - while (k--) res = maxPQ.dequeue().element; - - return res; -} From 81db9cae16f2b99040ab80c4b2009bf07774fcb1 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:55:01 +0800 Subject: [PATCH 18/25] Create Solution2.ts --- .../0215.Kth Largest Element in an Array/Solution2.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.ts diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.ts new file mode 100644 index 0000000000000..a56f83adfa4ef --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.ts @@ -0,0 +1,10 @@ +function findKthLargest(nums: number[], k: number): number { + const minQ = new MinPriorityQueue(); + for (const x of nums) { + minQ.enqueue(x); + if (minQ.size() > k) { + minQ.dequeue(); + } + } + return minQ.front().element; +} From df80a1901ee5eb9d1ba98363c0c712a8fa737f9d Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:55:18 +0800 Subject: [PATCH 19/25] Update Solution2.rs --- .../Solution2.rs | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.rs b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.rs index 589e6ddb82204..75e7003f6066a 100644 --- a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.rs +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution2.rs @@ -1,28 +1,14 @@ -use rand::Rng; +use std::collections::BinaryHeap; impl Solution { - pub fn find_kth_largest(mut nums: Vec, k: i32) -> i32 { - let k = k as usize; - let n = nums.len(); - let mut l = 0; - let mut r = n; - while l <= k - 1 && l < r { - nums.swap(l, rand::thread_rng().gen_range(l, r)); - let num = nums[l]; - let mut mark = l; - for i in l..r { - if nums[i] > num { - mark += 1; - nums.swap(i, mark); - } - } - nums.swap(l, mark); - if mark + 1 <= k { - l = mark + 1; - } else { - r = mark; + pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { + let mut minQ = BinaryHeap::new(); + for &x in nums.iter() { + minQ.push(-x); + if minQ.len() > k as usize { + minQ.pop(); } } - nums[k - 1] + -minQ.peek().unwrap() } } From cb93bed5fc2e4541331371571c6d621d57c61173 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:55:37 +0800 Subject: [PATCH 20/25] Create Solution3.py --- .../0215.Kth Largest Element in an Array/Solution3.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.py diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.py b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.py new file mode 100644 index 0000000000000..4d30bcae1371c --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.py @@ -0,0 +1,7 @@ +class Solution: + def findKthLargest(self, nums: List[int], k: int) -> int: + cnt = Counter(nums) + for i in count(max(cnt), -1): + k -= cnt[i] + if k <= 0: + return i From 72c1939ef9144e3b49c32a9f408a11c3e689e3b1 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:56:16 +0800 Subject: [PATCH 21/25] Create Solution3.java --- .../Solution3.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.java diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.java b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.java new file mode 100644 index 0000000000000..76ec4f8d00616 --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.java @@ -0,0 +1,16 @@ +class Solution { + public int findKthLargest(int[] nums, int k) { + Map cnt = new HashMap<>(nums.length); + int m = Integer.MIN_VALUE; + for (int x : nums) { + m = Math.max(m, x); + cnt.merge(x, 1, Integer::sum); + } + for (int i = m;; --i) { + k -= cnt.getOrDefault(i, 0); + if (k <= 0) { + return i; + } + } + } +} From c06626936c567a7565c8da8576cdb09473631a69 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:56:30 +0800 Subject: [PATCH 22/25] Create Solution3.cpp --- .../Solution3.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.cpp diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.cpp b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.cpp new file mode 100644 index 0000000000000..9f96b7f60cf7a --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + int findKthLargest(vector& nums, int k) { + unordered_map cnt; + int m = INT_MIN; + for (int x : nums) { + ++cnt[x]; + m = max(m, x); + } + for (int i = m;; --i) { + k -= cnt[i]; + if (k <= 0) { + return i; + } + } + } +}; From cdf624b737157ce0e32e1e85f8495a9fbe4da95f Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:56:40 +0800 Subject: [PATCH 23/25] Create Solution3.go --- .../Solution3.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.go diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.go b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.go new file mode 100644 index 0000000000000..982b822522ec7 --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.go @@ -0,0 +1,15 @@ +func findKthLargest(nums []int, k int) int { + cnt := map[int]int{} + m := -(1 << 30) + for _, x := range nums { + cnt[x]++ + m = max(m, x) + } + for i := m; ; i-- { + k -= cnt[i] + if k <= 0 { + return i + } + } + +} From ff21319470992d2a6dbf1a6b7ea4d5f002f5f743 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:56:54 +0800 Subject: [PATCH 24/25] Create Solution3.ts --- .../Solution3.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts new file mode 100644 index 0000000000000..12fe7734fb818 --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.ts @@ -0,0 +1,13 @@ +function findKthLargest(nums: number[], k: number): number { + const cnt: Record = {}; + for (const x of nums) { + cnt[x] = (cnt[x] || 0) + 1; + } + const m = Math.max(...nums); + for (let i = m; ; --i) { + k -= cnt[i] || 0; + if (k <= 0) { + return i; + } + } +} From 5139d8a897e67c570491d8107486210977ce36ec Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 1 Jul 2024 20:57:13 +0800 Subject: [PATCH 25/25] Create Solution3.rs --- .../Solution3.rs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.rs diff --git a/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.rs b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.rs new file mode 100644 index 0000000000000..321c6320b02fa --- /dev/null +++ b/solution/0200-0299/0215.Kth Largest Element in an Array/Solution3.rs @@ -0,0 +1,27 @@ +use std::collections::HashMap; + +impl Solution { + pub fn find_kth_largest(nums: Vec, k: i32) -> i32 { + let mut cnt = HashMap::new(); + let mut m = i32::MIN; + + for &x in &nums { + *cnt.entry(x).or_insert(0) += 1; + if x > m { + m = x; + } + } + + let mut k = k; + for i in (i32::MIN..=m).rev() { + if let Some(&count) = cnt.get(&i) { + k -= count; + if k <= 0 { + return i; + } + } + } + + unreachable!(); + } +}