面試的時候,被問到top k問題,以為回答維護乙個k大小的最小堆就沒事了。被面試官引導去思考其他方法,發現居然有快排來搞一搞的邪門方法,但是並沒有證明出複雜度為ko(
n)ko(n)
ko(n)(k
kk為常數)。查了像網上的,都是些奇怪的o(n
)+o(
n/2)
+o(n
/4).
..2n
)o(n)+o(n/2)+o(n/4)...o(
n)+o
(n/2
)+o(
n/4)...
2n)。覺得不大靠譜,決定自己嘗試的證明一下。
設d p(
n,k)
dp(n,k)
dp(n,k
)表示n
nn個數找出前k
kk大的時間複雜度。
顯然d p(
n,k)
=\displaystyle\sum_^k\frac(dp(n-i,k-i)+n)+\displaystyle\sum_^\frac(dp(i,k)+n)=n+\frac(\displaystyle\sum_^dp(n-i,k-i)+\displaystyle\sum_^dp(i,k))&\\\\0&\end
dp(n,k
)=⎩⎪
⎪⎪⎪⎨
⎪⎪⎪⎪
⎧i=
1∑k
n1(
dp(n
−i,k
−i)+
n)+i
=k+1
∑n−1
n1
(dp(
i,k)
+n)=
n+n1
(i=
1∑k−
1dp
(n−i
,k−i
)+i=
k+1∑
n−1
dp(i
,k))
0n>kn
≤kok,dp式子推出來了,打個簡單的暴力康康。
#include
using
namespace std;
const
int maxn =20;
double dp[maxn]
[maxn]
;int
main()
dp[n]
[k]=0;
for(
int i =
1; i < k; i++
)for
(int i = k+
1; i < n; i++
) dp[n]
[k]/
= n;
dp[n]
[k]+
= n;
}for
(int n =
1;n <= maxn-
5; n++)}
}return0;
}結果如圖
顯然,存在許多不止2n的地方。明顯關於時間複雜度小於2n的結論是錯的。接下來來嘗試證明一下。已知dp(
n,k)
=n+\frac(\displaystyle\sum_^dp(n-i,k-i)+\displaystyle\sum_^dp(i,k))&\\\\0&\end
dp(n,k
)=⎩⎪
⎪⎪⎪⎨
⎪⎪⎪⎪
⎧n+
n1(
i=1∑
k−1
dp(n
−i,k
−i)+
i=k+
1∑n−
1dp
(i,k
))0
n>kn
≤k(得出如果字首和優化的話求dp(
n,k)
dp(n,k)
dp(n,k
)是o(nk
)o(nk)
o(nk
)的複雜度)
。。。嘗試算一下通式,發現是一件非常不靠譜的事情。列印了下,發現dp(
1500
,750
)dp(1500,750)
dp(150
0,75
0)的有1500的3倍多了,感覺應該還是有帶log
loglo
g的。等有時間or大佬再來算一下吧。
快排時間複雜度詳細解釋
1 快速排序遞迴版 def quick sort arr if len arr 2 return arr 這是基線條件 else a arr 0 smaller i for i in arr 1 if i a bigger i for i in arr 1 if i a return quick s...
快排求逆序數 快排與歸併時間複雜度比較
本文參考其他用快排求逆序數的方法。在用快排求解逆序數前,我先考慮了這個問題,1 歸併和快排的時間複雜度都是nlog n 為什麼不用歸併?我認為應該是由於快排在每次合併時都有用到臨時陣列,然後每次還需要把臨時陣列重新copy到原陣列中 增加了時間複雜度 快排雖然也存在最壞的情況,即n 2,但是由於其隨...
鍊錶快排和時間複雜度分析
前端時間去面試,碰到問題,快排的鍊錶實現和時間複雜度分析,非常基礎,但是當時完全沒想到社招面試會涉及到這麼基礎的東西,回答的非常不完美,現在總結,以致後人 節點定義 struct node 實現 node part node begin,node end q q next tmp p value p...