算法思想
取一个pivot,以pivot将原数组划分为两部分大小分别是x和y,确定了pivot的位置,现在知道pivot是第y+1大,如果k比y+1小,继续往右边找,如果k比y+1大,往左边找,如果k等于y+1,说明找到了。
主定理(master theorem)
假设有递推表达式
T
(
n
)
=
a
T
(
n
b
)
+
f
(
n
)
T(n)=aT(\frac n b)+f(n)
T(n)=aT(bn)+f(n) ,其中
n
n
n为问题规模,
a
a
a为递推的子问题数量,
n
b
\frac n b
bn为每个子问题的规模(假设每个子问题的规模基本一样),
f
(
n
)
f(n)
f(n)为递推以外进行的计算工作。
a
≥
1
,
b
>
1
a≥1,b>1
a≥1,b>1为常数,
f
(
n
)
f(n)
f(n) 为函数,
T
(
n
)
T(n)
T(n)为非负整数。则有以下结果(分类讨论):
a.
若
f
(
n
)
=
O
(
n
l
o
g
b
a
−
ϵ
)
,
ϵ
>
0
,
则
T
(
n
)
=
Θ
(
n
l
o
g
b
a
)
若f(n)=O(n^{log_ba-\epsilon}),\epsilon>0,则T(n)=\Theta(n^{log_ba})
若f(n)=O(nlogba−ϵ),ϵ>0,则T(n)=Θ(nlogba)。
b.
若
f
(
n
)
=
Θ
(
n
l
o
g
b
a
)
,
则
T
(
n
)
=
Θ
(
n
l
o
g
b
a
l
o
g
n
)
若f(n)=\Theta(n^{log_ba}),则T(n)=\Theta(n^{log_ba}logn)
若f(n)=Θ(nlogba),则T(n)=Θ(nlogbalogn)。
c.
若
f
(
n
)
=
Ω
(
n
l
o
g
b
a
+
ϵ
)
,
ϵ
>
0
,
且
对
于
某
个
常
数
c
<
1
和
所
有
充
分
大
的
n
有
a
f
(
n
b
)
≤
c
f
(
n
)
,
那
么
T
(
n
)
=
Θ
(
f
(
n
)
)
若f(n)=\Omega(n^{log_ba+\epsilon}),\epsilon>0,且对于某个常数c<1和所有充分大的n有af(\frac nb) \leq cf(n),那么T(n)=\Theta(f(n))
若f(n)=Ω(nlogba+ϵ),ϵ>0,且对于某个常数c<1和所有充分大的n有af(bn)≤cf(n),那么T(n)=Θ(f(n))。
证明
上面算法每次规模缩小一半,除此以外需要n次比较,所以可以写出递推表达式是
T
(
n
)
=
T
(
n
2
)
+
n
T(n) = T(\frac n 2)+n
T(n)=T(2n)+n。
由主定理可知,
a
=
1
,
b
=
2
,
l
o
g
a
b
=
0
a=1,b=2,log_ab=0
a=1,b=2,logab=0
有
f
(
n
)
=
n
=
Ω
(
n
ϵ
)
,
ϵ
取
1
,
c
取
1
2
,
所
以
T
(
n
)
=
Θ
(
n
)
f(n)=n=\Omega(n^\epsilon), \epsilon取1,c取\frac 12,所以T(n)=\Theta(n)
f(n)=n=Ω(nϵ),ϵ取1,c取21,所以T(n)=Θ(n)。
代码实现
private int partition(int[] nums, int l, int r) {
int pivot = nums[l];
while (l < r) {
while (l < r && pivot <= nums[r]) r--;
if (l < r) nums[l] = nums[r];
while (l < r && pivot >= nums[l]) l++;
if (l < r) nums[r] = nums[l];
}
nums[l] = pivot;
return l;
}
public int findKthLargest(int[] nums, int l, int r, int k) {
if (l == r && k == 1) return nums[l];
int pivotIndex = partition(nums, l, r);
int y = r - pivotIndex;
if (k < y + 1) return findKthLargest(nums, pivotIndex + 1, r, k);
else if (k > y + 1) return findKthLargest(nums, l, pivotIndex - 1, k - y - 1);
else return nums[pivotIndex];
}