日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

线性时间选择算法(Java)

發布時間:2023/12/9 java 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线性时间选择算法(Java) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線性時間選擇算法(Java)

  • 線性時間選擇算法
    • 隨機劃分線性選擇
      • 分析
      • 代碼
    • 利用中位數線性時間選擇
      • 分析
      • 例題
      • 代碼

線性時間選擇算法

最近算法課的知識點之一,自己以前沒遇見過(是我菜了沒錯),這次寫一篇。

那么什么是線性時間選擇呢???一句話,在線性時間內完成選擇

一般情況下是這樣的,我們想要找出一個數組中的最大值或最小值,那就只需要一次排列,然后輸出第一個或最后一個元素就行了,但如果是要找出一個數組中的第k小的元素呢?

  • 在某些特殊情況下,很容易設計出解選擇問題的線性時間算法。如:當要選擇最大元素或最小元素時,顯然可以在O(n)時間完成。(遍歷一次)

  • 一般的選擇問題,特別是中位數的選擇問題似乎比最小(大)元素要難。但實際上,從漸近階的意義上,它們是一樣的。也可以在O(n)時間完成。

  • 之前我記得我更過一篇,里面說到就是先排個序,然后通過下標去得到,因此這個問題的解決效率取決于排序算法的效率。

    但是現在不一樣了,我們有了更好的辦法。

    隨機劃分線性選擇

    分析

    隨機劃分線性選擇。模仿快速排序算法,對數組在left——right范圍內進行一次劃分(partition方法,我們這里默認采用隨機元素為基準),得到基準下標i,不大于基準的在左邊,比基準大的在右邊。計算出left——i(包含i)中有多少個元素(j),與k進行比較。

  • 如果k<j,說明當前left——right中第k小的在左邊序列中,那么從left——i-1繼續上述步驟尋找第k小。
  • 如果k=j,說明基準i就是left——right中第k小,返回a[j]。(因為前面的都不大于它,后面的都大于它,不管左邊是序列怎么排的,整體第k(j)小就是他)
  • 如果k>j,說明第k小在右邊序列,大于基準a[i],那么從i+1——right繼續劃分,并將k改為k-j。(整體序列提出了前j個元素,那么第k小在剩下的序列中就是第k-j小了)
  • 一直到left=right的時候就可以返回a[left]了(其實我覺得如果有上述2的情況的話就不需要這個了)

    這是課堂上PPT給的思路

    這是算法導論的(就是我剛剛說的)

    代碼

    /** @Title randomizedSelect* @Description 基于隨機元素為基準的線性時間選擇* @author 滑技工廠* @Date 2020/3/26* @param [a, L, R, k -> L---R中的第k小]* @return int* @throws*/public static int randomizedSelect(int[] a, int L, int R, int k) {if (L == R)return a[L];//獲取為基準的隨機元素的下標int i = randomizedPartition(a, L, R);//j為劃分后左序列到基準(包含基準)的元素個數int j = i - L + 1;if (k < j)//如果k小于j,說明在基準i的左邊return randomizedSelect(a, L, i - 1, k);else if (k == j)//return a[i];else//k大于j 說明在i的右邊序列return randomizedSelect(a, i + 1, R, k - j);}

    利用中位數線性時間選擇

    分析

    算法的思路:如果能在線性時間內找到一個劃分基準使得按這個基準所劃分出的2個子數組的長度都至少為原數組長度的ε倍(0<ε<1),那么就可以在最壞情況下用O(n)時間完成選擇任務。例如,當ε=9/10,算法遞歸調用所產生的子數組的長度至少縮短1/10。所以,在最壞情況下,算法所需的計算時間T(n)滿足遞推式T(n)<=T(9n/10)+O(n)。由此可得T(n)=O(n)。

    先描述下過程。
    將n個輸入元素劃分成n/5個組,每組5個元素,最只可能有一個組不是5個元素。用任意一種排序算法,將每組中元素排好序,并取出中位數,共n/5個。

    遞歸調用Select來找出這n/5個元素中的中位數。如果n/5是個偶數,就找它兩個中位數中較大的一個。以該元素作為劃分基準。

    這種情況下,找出的基準x至少比3(n-5)/10個元素大,同理也比3(n-5)/10個元素小。(下圖中箭頭指向是從大到小,紅+藍的數量為3(n-5)/10)而當n>=75時,3(n-5)/10>=n/4所以按此基準劃分所得的兩個子數組的長度都至少縮短1/4

    得到劃分基準后,后面就和第一個一樣,計算左序列個數,和k進行比較。判斷在左序列還是右序列,在遞歸調用該方法(k在右序列仍要減j),直到k=j為止,返回那個基準。

    例題



    代碼

    /** @Title select* @Description 利用中位數線性時間選擇* @author 滑技工廠* @Date 2020/3/27* @param [a, l, r, k]* @return int* @throws*/public static int select(int[] a, int l, int r, int k) {if (r - l < 75) {insertSort(a, l, r); //用插入排序進行排序return a[l + k - 1];}int group = (r - l + 5) / 5;for (int i = 0; i < group; i++) {int left = l + 5 * i;int right = (l + i * 5 + 4) > r ? r : l + i * 5 + 4; //如果超出右邊界就用右邊界賦值int mid = (left + right) / 2;insertSort(a, left, right);swap(a, l + i, mid); // 將各組中位數與前i個}int pivot = select(a, l, l + group - 1, (group + 1) / 2); //找出中位數的中位數int p = partition(a, l, r, pivot); //用中位數的中位數作為基準的位置int j = p - l + 1; //leftNum用來記錄基準位置的前邊的元素個數if (k == j)return a[p];else if (k < j)return select(a, l, p - 1, k);else //若k在基準位子的后邊,則要從基準位置的后邊數起,即第(k - leftNum - 1)個return select(a, p + 1, r, k - j - 1);}

    詳細代碼去我的G站

    作業又完成了一個 (^-^)V

    總結

    以上是生活随笔為你收集整理的线性时间选择算法(Java)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。