top k快排複雜度討論

2021-10-22 14:41:28 字數 2257 閱讀 2802

面試的時候,被問到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−

1​dp

(n−i

,k−i

)+i=

k+1∑

n−1​

dp(i

,k))

0​n>kn

≤k​ok,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−

1​dp

(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...