2
2
3
3
4
4
5
+ < https://leetcode.com/problems/kth-largest-element-in-an-array/ >
6
+
5
7
6
8
### 想法
7
9
11
13
12
14
#### O(nlgn)
13
15
14
- 看这段代码 ,简直是Pythonize的代表作.
16
+ 看这段Swift代码 ,简直是Pythonize的代表作.
15
17
16
18
如果需要reverse排序可` reversed = names.sort(>) `
17
19
18
20
[ sort参见] ( https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html )
19
21
22
+ 因为nums是不可变,所以其实这样也蛮浪费的,但是可以AC
23
+
24
+ ``` swift
25
+ class Solution {
26
+ func findKthLargest (_ nums : [Int ], _ k : Int ) -> Int {
27
+ var sortedNums = nums.sorted ()
28
+ return sortedNums[nums.count - k]
29
+ }
30
+ }
31
+ ```
32
+
33
+
34
+
20
35
21
36
#### O(n) + O(klgn)
22
37
@@ -67,10 +82,13 @@ class Solution(object):
67
82
68
83
69
84
85
+ #### O(n)
86
+
87
+ 发现这个O(n) 是average case, worst case 是 O(n^2)
88
+
89
+ CLRS ch9.3 可以找到, wikipedia可以找到: https://en.wikipedia.org/wiki/Quickselect
70
90
71
- #### O(n)
72
91
73
- CLRS ch9.3 可以找到
74
92
75
93
76
94
[ 最佳资源在此处] ( https://github.com/raywenderlich/swift-algorithm-club/tree/master/Kth%20Largest%20Element )
@@ -81,7 +99,7 @@ CLRS ch9.3 可以找到
81
99
注意写的是第k小的,然后这里是求第k大的
82
100
< https://rosettacode.org/wiki/Quickselect_algorithm#Python >
83
101
84
- ```
102
+ ``` python
85
103
class Solution (object ):
86
104
def findKthLargest (self , nums , k ):
87
105
"""
@@ -120,7 +138,54 @@ class Solution(object):
120
138
```
121
139
122
140
123
- 时间复杂度是O(n),CLRS里面有出现这个算法和证明
141
+
142
+ 对照wikipedia写出来的:
143
+
144
+ ``` python
145
+ class Solution (object ):
146
+ def findKthLargest (self , nums , k ):
147
+ """
148
+ :type nums: List[int]
149
+ :type k: int
150
+ :rtype: int
151
+ """
152
+ def partition (lst , left , right , pivotIndex ):
153
+ pivotValue = lst[pivotIndex]
154
+ lst[pivotIndex], lst[right] = lst[right], lst[pivotIndex]
155
+ storeIndex = left
156
+ for i in range (left, right):
157
+ if lst[i] < pivotValue:
158
+ lst[storeIndex], lst[i] = lst[i], lst[storeIndex]
159
+ storeIndex += 1
160
+ lst[right], lst[storeIndex] = lst[storeIndex], lst[right]
161
+ return storeIndex
162
+
163
+ # kth smallest
164
+ def select (lst , left , right , k ):
165
+ if left == right:
166
+ return lst[left]
167
+ pivotIndex = left
168
+ pivotIndex = partition(lst, left, right, pivotIndex)
169
+
170
+ if k == pivotIndex:
171
+ return lst[k]
172
+ elif k < pivotIndex:
173
+ return select(lst, left, pivotIndex - 1 , k)
174
+ else :
175
+ return select(lst, pivotIndex + 1 , right, k)
176
+ n = len (nums)
177
+ return select(nums, 0 , n - 1 , n - k)
178
+ ```
179
+
180
+
181
+
182
+ 跟上面的方法区别也不大,一个recursion, 一个for loop,注意下面跟初等算法解释的对比,因为这里我们并没有去减小lst,所以我们的k是不用变化的。
183
+
184
+
185
+
186
+
187
+
188
+
124
189
125
190
126
191
摘自初等算法的解释,我觉得解释的非常棒
@@ -135,7 +200,7 @@ class Solution(object):
135
200
2 . 若k <= |A|,则第k小的元素必然在A中,我们可以丢弃子序列B,然后在A中进一步查找;
136
201
3 . 若|A| < k,则第k小的元素必然在B中,我们可以丢弃子序列A,然后在B中进一步查找第(k − |A|)小的元素。
137
202
138
- 注意下划线部分强调了递归的特性。理想情况下,我们总是将序列划分为相 等长度的两个子序列A和B,这样每次都将问题的规模减半,因此性能为线性时 间O (n)。
203
+ 注意下划线部分强调了递归的特性。理想情况下,我们总是将序列划分为相 等长度的两个子序列A和B,这样每次都将问题的规模减半,因此性能为线性时间O (n)。
139
204
140
205
141
206
关键问题是如何实现划分,将前m小的元素放入一个子序列中,将剩余元素放入另一个中。
@@ -150,4 +215,11 @@ class Solution(object):
150
215
151
216
4 . 若|A| > k − 1,递归在A中寻找第k小的元素;
152
217
153
- 5 . 否则,递归在B中寻找第(k − 1 − |A|)小的元素;
218
+ 5 . 否则,递归在B中寻找第(k − 1 − |A|)小的元素;
219
+
220
+
221
+
222
+
223
+
224
+
225
+
0 commit comments