Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3b2f146

Browse filesBrowse files
committed
[zh-hans en] update kth_largest_element.md: add iterative implementation
1 parent 76b4447 commit 3b2f146
Copy full SHA for 3b2f146

3 files changed

+115-3Lines changed: 115 additions & 3 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎en/basics_sorting/quick_sort.md‎

Copy file name to clipboardExpand all lines: en/basics_sorting/quick_sort.md
+1-1Lines changed: 1 addition & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ The output:
286286
Having analyzed three implementations of quick sort, we may grasp one key difference between *quick sort* and *merge sort* :
287287

288288
1. Merge sort divides the original array into two sub-arrays, and merges the sorted sub-arrays to form a totally ordered one. In this case, recursion happens before processing(merging) the whole array.
289-
2. Quick sort divides the original array into two sub-arrays, and then sort them. The whole array is sorted as soon as the sub-arrays get sorted. In this case, recursion happens after processing(partition) the whole array.
289+
2. Quick sort divides the original array into two sub-arrays, and then sort them. The whole array is ordered as soon as the sub-arrays get sorted. In this case, recursion happens after processing(partition) the whole array.
290290

291291
Robert Sedgewick's presentation on [quick sort](http://algs4.cs.princeton.edu/23quicksort/) is strongly recommended.
292292

Collapse file

‎en/integer_array/kth_largest_element.md‎

Copy file name to clipboardExpand all lines: en/integer_array/kth_largest_element.md
+57-1Lines changed: 57 additions & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Trail and error: Comparison-based sorting algorithms don't work because they inc
2929

3030
By quick sorting, we get the final index of a pivot. And by comparing that index with `K`, we decide which side (the greater or the smaller) of the pivot to recurse on.
3131

32-
### Java
32+
### Java - Recursion
3333

3434
```java
3535
public class Solution {
@@ -79,6 +79,62 @@ b. final index of pivot equals K.
7979

8080
Since 'Kth **largest**' is wanted, numbers greater than pivot are placed to the left and numbers smaller to the right, which is a little different with typical quick sort code.
8181

82+
### Java - Iteration
83+
84+
Recursive code is easier to read than to write, and it demands some experience and skill. Here is an iterative implementation.
85+
86+
```
87+
class Solution {
88+
public int findKthLargest(int[] A, int k) {
89+
if (A == null || A.length == 0 || k < 0 || k > A.length) {
90+
return -1;
91+
}
92+
93+
int lo = 0, hi = A.length - 1;
94+
while (lo <= hi) {
95+
int idx = partition(A, lo, hi);
96+
if (idx == k - 1) {
97+
return A[idx];
98+
} else if (idx < k - 1) {
99+
lo = idx + 1;
100+
} else {
101+
hi = idx - 1;
102+
}
103+
}
104+
105+
return -1;
106+
}
107+
108+
private int partition(int[] A, int lo, int hi) {
109+
int pivot = A[lo], i = lo + 1, j = hi;
110+
while (i <= j) {
111+
while (i <= j && A[i] > pivot) {
112+
i++;
113+
}
114+
while (i <= j && A[j] <= pivot) {
115+
j--;
116+
}
117+
if (i < j) {
118+
swap(A, i, j);
119+
}
120+
}
121+
swap(A, lo, j);
122+
123+
return j;
124+
}
125+
126+
private void swap(int[] A, int i, int j) {
127+
int tmp = A[i];
128+
A[i] = A[j];
129+
A[j] = tmp;
130+
}
131+
}
132+
```
133+
134+
### Src Code Analysis
135+
136+
The `while` loop in `findKthLargest` is very much like that in `binary search`. And `partition` method is just the same as quick sort partition.
137+
82138
### Complexity
83139

84140
Time Complexity. Worse case (when the array is sorted): ***n + n - 1 + ... + 1 = O(n^2)*** . Amortized complexity: ***n + n/2 + n/4 + ... + 1 = O(2n)=O(n)*** .
Collapse file

‎zh-hans/integer_array/kth_largest_element.md‎

Copy file name to clipboardExpand all lines: zh-hans/integer_array/kth_largest_element.md
+57-1Lines changed: 57 additions & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ adding this problem and creating all test cases.
2727

2828
找第 K 大数,基于比较的排序的方法时间复杂度为 $$O(n)$$, 数组元素无区间限定,故无法使用线性排序。由于只是需要找第 K 大数,这种类型的题通常需要使用快排的思想解决。[Quick Sort](http://algorithm.yuanbin.me/zh-hans/basics_sorting/quick_sort.html) 总结了一些经典模板。这里比较基准值最后的位置的索引值和 K 的大小关系即可递归求解。
2929

30-
### Java
30+
### Java - 递归求解
3131

3232
```java
3333
public class Solution {
@@ -76,6 +76,62 @@ public class Solution {
7676
递归的终止条件有两个,一个是左边界的值等于右边界(实际中其实不会有 l > u), 另一个则是索引值 `m + 1 == k`.
7777
这里找的是第 K 大数,故为降序排列,for 循环中使用`nums[i] > nums[left]` 而不是小于号。
7878

79+
### Java - 迭代求解
80+
81+
递归代码看上去顺理成章,实际上构造递归方法的参数、返回值是需要经验技巧的,自己写起来就会发现机关重重,一次性做到 bug-free 并不容易。下面是一个迭代版的实现。
82+
83+
```
84+
class Solution {
85+
public int findKthLargest(int[] A, int k) {
86+
if (A == null || A.length == 0 || k < 0 || k > A.length) {
87+
return -1;
88+
}
89+
90+
int lo = 0, hi = A.length - 1;
91+
while (lo <= hi) {
92+
int idx = partition(A, lo, hi);
93+
if (idx == k - 1) {
94+
return A[idx];
95+
} else if (idx < k - 1) {
96+
lo = idx + 1;
97+
} else {
98+
hi = idx - 1;
99+
}
100+
}
101+
102+
return -1;
103+
}
104+
105+
private int partition(int[] A, int lo, int hi) {
106+
int pivot = A[lo], i = lo + 1, j = hi;
107+
while (i <= j) {
108+
while (i <= j && A[i] > pivot) {
109+
i++;
110+
}
111+
while (i <= j && A[j] <= pivot) {
112+
j--;
113+
}
114+
if (i < j) {
115+
swap(A, i, j);
116+
}
117+
}
118+
swap(A, lo, j);
119+
120+
return j;
121+
}
122+
123+
private void swap(int[] A, int i, int j) {
124+
int tmp = A[i];
125+
A[i] = A[j];
126+
A[j] = tmp;
127+
}
128+
}
129+
```
130+
131+
### 源码分析
132+
133+
`findKthLargest` 里的 `while` 循环体有种二分搜索的既视感,`partition` 就是标典型的快排分区写法。
134+
79135
### 复杂度分析
80136

81137
最坏情况下需要遍历 $$ n + n - 1 + ... + 1 = O(n^2)$$, 平均情况下 $$n + n/2 + n/4 + ... + 1 = O(2n)=O(n)$$. 故平均情况时间复杂度为 $$O(n)$$. 交换数组的值时使用了额外空间,空间复杂度 $$O(1)$$.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.