【算法】线性时间选择——第k大(小)元素问题
生活随笔
收集整理的這篇文章主要介紹了
【算法】线性时间选择——第k大(小)元素问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 前言
- 分治算法之第k小元素
- 分治算法之第k大元素
前言
分治算法之第k小元素
(1)隨機選擇序列中第 i 個作為基準元素,統計比基準元素小的元素個數, 如果 個數 比 k 小,說明我們要找的第 k 小元素在基準后半部分,個數比 k 大,說明在前半部分。
(2)對于無序序列a[s…t],在其中查找第k小元素的過程:
- 若s=t,即其中只有一個元素,返回a[s]
- 若s!=t,表示該序列中有兩個或兩個以上元素,以基準為中心將其劃分為a[s…i]和a[i+1…t],a[s…i]中所有元素均小于等于a[i],a[i+1…t]中所有元素均大于a[i]
j = i-s+1,統計小于等于a[i]的元素個數
j>=k,第k小元素在a[s…i]中,遞歸在a[s…i]中尋找第k小元素
j < k,第k小元素在a[i+1…t]中,遞歸在a[i+1…t]中尋找第k-j小元素
一個無序數列隨機找到一個下標作為基準,每次分區,數列減少一部分,因為每次可以確定第 k 小元素是在基準的前半部分,還是后半部分,如果確定在前半部分,后半部分的數就不需要管了,
T(n)=T(n/b)+O(n)=O(n)
分治算法之第k大元素
在前面那個算法改成比基準大的元素放在前半部分,小的放在后半部分即可。
public class Demo {public static void main(String[] args) {int[] arr={3,1,5,7,8,2,9};System.out.println(randomizedSelect(arr, 0, arr.length - 1, 1));}public static int randomizedSelect(int[] a,int s,int t,int k){//a[s,t]//s == t ==>說明只有一個元素, 輸出if (s == t){return a[s];}//s < t 二個或二個元素以上//找到基準i 的位置int i = randomizedPartition(a,s,t);//大于等于 基準的個數int j = i - s + 1;//k <= j 說明第k大的元素在 前半部分a[s,i] 反之在后半部分a[i+1,t]if (j >= k){return randomizedSelect(a,s,i,k);}else {return randomizedSelect(a,i+1,t,k-j);}}//隨機產生一個基準的下標===》與第1個元素交換===》分區public static int randomizedPartition(int[] a,int p,int q){//a[p,q]int r = random(p,q);swap(a,r,p);int i = partition(a, p, q);return i;}/*** 以第一個元素為基準 分區* @param a 數組a* @param p a[p,q]* @param q a[p,q]* @return 分區后基準下標i a[p,i]和a[i+1,q]*/public static int partition(int[] a,int p,int q){int x = a[p];int i = p;for (int j = p; j <= q; j++) {if (a[j] > x){i++;swap(a,i,j);}}swap(a,p,i);return i;}/*** 數組交換函數* @param a 數組a* @param p 下標p* @param q 下標q*/public static void swap(int[] a,int p,int q){int t = a[p];a[p] = a[q];a[q] = t;}/*** 產生一個[p,q]的隨機數* @param p [p,q]* @param q [p,q]* @return [p,q]的隨機數*/public static int random(int p,int q){Random random = new Random();return Math.abs(random.nextInt())%(q-p+1) + p;}}總結
以上是生活随笔為你收集整理的【算法】线性时间选择——第k大(小)元素问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [html] 怎么去除img之间存在的
- 下一篇: 工作409-修复npm ERR! cb(