top k 問題的幾種解決方法

2021-08-15 17:29:07 字數 2048 閱讀 2255

top k問題是指給定一組數量為n的數,從中找出前k大的數或第k大的數(k <= n)。由於只要能找出前k大的數,即可以得到第k大的數。所以下面先介紹解決前k大數問題的幾種思路:

由於我們只需要找到陣列nums的前k大的數,所以不需要對整個資料進行排序,只需要保持前k大的數有序即可。所以我們可以維護乙個大小為k的陣列tk:

複雜度:對tk排序的複雜度為o(k*logk),向tk插入資料的複雜度為o(k), 所以遍歷陣列nums並向tk插入資料的複雜度為o(n*k),總的複雜度為o(k*logk + n*k) 近似為 o(k*n)

如果k的值過大,演算法的複雜度會相應增大

**

vector

solve1(vector

&nums, int k)

tk[j] = tk[j-1];

j--;

}if(j == 0)

tk[j] = t;}}

return tk;

}

我們可以將待找陣列nums建立為乙個大根堆,然後從建好的堆中一次找出最大的k個數即可。

複雜度:使用篩選法建堆的複雜度為o(n), 然後從大根堆中找出前k大數的複雜度為o(k*logn),所以總的複雜度為:o(n + k*logn)

顯然這個演算法的複雜度要低於部分排序。

**

vector

solve2(vector

&nums, int k)

return result;

}void adjust(vector

&nums, int i, int n)

nums[parent] = t;

}

分析前面的部分排序演算法,我們可以發現有太多的時間浪費在了對陣列tk的插入操作中,為了提高插入的效率,我們可以將陣列tk組織為乙個小根堆,對於小根堆的插入操作複雜度為o(logk),這顯然要優於直接插入的複雜度o(k)。

複雜度:總的複雜度為 o(n*logk)

**

vector

solve3(vector

&nums, int k)

//對tk排序

for(int i = k-1; i >= 0; i--)

return tk;

}void adjust(vector

&nums, int i, int n)

nums[parent] = t;

}

還有一種演算法是基於快速排序的,我們知道每趟快排都會選定乙個基準值,一趟快排後,基準值右邊的所有數都大於這個基準值,所以我們可以通過選取合適的部分遞迴地對這些部分進行一趟快排,直到基準值右邊的數為k個,那麼我們就得到了陣列的前k大的數:

1. 首先對陣列nums進行一趟快排

2. 然後根據關鍵值key的位置進行判斷

3. 如果key的下標 i < n-k : 對i右邊的部分進行一趟快排,然後重複步驟2

4. 如果key的下標 i > n-k : 對i左邊的部分進行一趟快排,然後重複步驟2

5. 如果key的下標 i == n-k ,那麼就返回key(或 i )

上述算中,如果返回key就是陣列中第k大的數,如果返回i就是前k大數的位置,下面的演算法給出的是乙個尋找第k大數的演算法,稍作修改就可以得到前k大的數。

複雜度:o(n)

**

int qselect(vector

&nums, int left, int right, int k)

nums[low] = key;

if(low == nums.size()-k)

return key;

else

if(low < nums.size()-k)

return qselect(nums, low+1, right, k);

else

return qselect(nums, left, low-1, k);

}}

repo init失敗的幾種解決方法

試了幾天,終於解決了同步repo init失敗的問題。謹此記錄一下。希望對讀者有用。由於每個人的情況都不一樣。所以我這裡會列舉我嘗試的所有方法。注意repo sync的問題不在本文討論的範圍內。mac,10.15 0s,git 目錄下有.repo資料夾。在這個資料夾下包含 error ssl cer...

Hash衝突的幾種解決方法

1.開放定值法 也叫再雜湊法,當關鍵字key的雜湊位址p h key 出現衝突時,以p為基礎,產生另乙個雜湊位址p1,如果p1仍然衝突,再以p為基礎,產生另乙個雜湊位址p2,直到找出乙個不衝突的雜湊位址pi 將相應元素存入其中。通常都是用以下公式計算 hi h key di m i 1,2,n 其中...

java解決topk問題

面試題中經常用到堆,這裡總結一下。方法一 對源資料中所有資料進行排序,取出前k個資料,就是topk。但是當資料量很大時,只需要k個最大的數,整體排序很耗時,效率不高。方法二 維護乙個k長度的陣列a,先讀取源資料中的前k個放入陣列,對該陣列進行公升序排序,再依次讀取源資料第k個以後的資料,和陣列中最小...