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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

分治——线性时间选择算法

發(fā)布時(shí)間:2023/12/9 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分治——线性时间选择算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 1. 選擇問(wèn)題
    • 2. 解決方法
    • 3. 代碼示例

顧名思義,“線性時(shí)間選擇”就是“選擇問(wèn)題”的“線性時(shí)間”算法。

1. 選擇問(wèn)題

元素選擇問(wèn)題:給定一個(gè)能夠線性排序的集合(該集合中有 n 個(gè)元素)和 一個(gè)整數(shù) k(1≤k≤n1 \le k \le n1kn) ,找出這 n 個(gè)元素中第 k 小的元素。

時(shí)間下界:

  • 當(dāng) k=1或k=nk = 1 或 k = nk=1k=n時(shí),時(shí)間復(fù)雜度為 O(n)O(n)O(n)

  • 當(dāng) k≤n/log(n)或k≥n?n/log(n)時(shí)k \le n/log(n) 或 k \ge n - n/log(n)時(shí)kn/log(n)kn?n/log(n)時(shí),時(shí)間復(fù)雜度為O(n+klog(n))=O(n)O(n + klog(n)) = O(n)O(n+klog(n))=O(n)(堆排序)

2. 解決方法

方法一:先排序,再找第 k 小的數(shù)。O(nlogn)O(nlogn)O(nlogn)時(shí)間

方法二:隨機(jī)選擇算法:使用快速排序方法, 最多對(duì)一段繼續(xù)分解 最壞時(shí)間O(n2)O(n^2)O(n2), 平均時(shí)間O(n)O(n)O(n)

  • RamdomizedPartition(a, p, r) 快排中的分解算法

  • i=Ramdom(p,r) //在p:r中隨機(jī)選擇一個(gè)數(shù)i

  • 交換 a[i] 與 a[p] //將a[i]換到左端點(diǎn)

  • 執(zhí)行Partition(a,p,r)

  • RamdomizedPartition(a, p, r) //排序a[p:r] { i = Ramdom(p, r); swap(a[i], a[p]);return Partition(a, p, r); }
  • RandomSelect(a, p, r)

    RSelect(a,p,r,k) //選擇a[p:r]中第k小數(shù) { if (p == r)return a[p];mid=RamdomizePartition(a, p, r); if( mid >= k)return (RSelect(a, p, mid, k)); else return (RSelect(a, mid + 1, r, k - mid); } //初略時(shí)間分析: T(n) = T(9n/10) + O(n) = O(n)
  • 方法三:線性時(shí)間選擇算法 Select() :對(duì)快速排序的改進(jìn),最壞時(shí)間O(n)O(n)O(n)

  • 將 n 個(gè)元素,分成?n/5?\lceil n/5 \rceil?n/5?組,取出每組的中位數(shù)(第三小的元素)
  • 取出?n/5?\lceil n/5 \rceil?n/5?個(gè)中位數(shù)的中位數(shù)(Select函數(shù)可以取中位數(shù))
  • 利用快排中的分解函數(shù) Partition(),以所求中位數(shù)為基準(zhǔn),劃分 a[p : r] 為兩段。
  • 取其中一段進(jìn)行遞歸。
  • template <typename Type> Type Select(Type a[], int p, int r, int k) { if( r - p < 75 ) { 直接對(duì)數(shù)組a[p:r]排序; return a[p+k-1];}for( int i = 0; i <= (r - p - 4) / 5 ; i++ ) //分 n/5 組, 取各組中位數(shù){swap(a[p + 5*i]至a[p+5*i+4]的第3小元素, a[p+i]);}Type x = Select(a, p, p+(r-p-4)/5, (r-p-4)/10); //取中位數(shù)的中位數(shù), T(n/5)int i = Partition(a, p, r, x), j = i - p + 1; if ( k == j ) return a[i];else if ( k < j ) return Select(a,p,i-1,k); //選擇左片遞歸, 最多T(3n/4)else return Select(a,i+1,r,k-j); //選擇右片遞歸, 最多T(3n/4)}

    時(shí)間復(fù)雜度分析:

    總結(jié):算法優(yōu)化的歷程

    算法快排隨機(jī)選擇線性時(shí)間選擇
    時(shí)間復(fù)雜度O(nlog(n))O(nlog(n))O(nlog(n))O(n)??O(n2)O(n) -- O(n^2)O(n)??O(n2)O(n)O(n)O(n)
    基準(zhǔn)值a[p]random中位數(shù)

    3. 代碼示例

    附:line-time-select.c

    #include <stdio.h> #define MAX 100000 int num[MAX]; // 選擇排序 void slsort(int p, int q) {for (int i = p + 1; i <= q; i++){int temp = num[i], j = i - 1;while (j >= p){if (num[j] > temp){num[j + 1] = num[j];j--;}elsebreak;}num[j + 1] = temp;} } // 分解函數(shù) int Partition(int p, int q, int mid) {int i = p, j = q;while (i <= q && j >= p){while (num[i] < mid){i++;}while (num[j] > mid){j--;}if (i >= j)break;else{int temp = num[i];num[i] = num[j];num[j] = temp;i++, j--;}}return j; } // 選擇函數(shù) int Select(int p, int q, int k) {if (q - p < 75){slsort(p, q);return num[p + k - 1];}// 選出 n/5 組中每個(gè)組的中位數(shù)for (int i = 0; i <= (q - p - 4) / 5; i++){slsort(p + 5 * i, p + 5 * i + 4);int temp = num[p + 5 * i + 2];num[p + 5 * i + 2] = num[p + i];num[p + i] = temp;}// 選出各種中位數(shù)的中位數(shù) midint mid = Select(p, p + (q - p - 4) / 5, ((q - p - 4) / 5 + 1) / 2);// 以 mid 為基準(zhǔn)進(jìn)行分解int mid_id = Partition(p, q, mid);int mid_rank = mid_id - p + 1;// 遞歸條件判斷if (k == mid_rank){return num[mid_id];}else if (k < mid_rank){return Select(p, mid_id, k);}else{return Select(mid_id + 1, q, k - mid_rank);} } int main(int argc, char const *argv[]) {int i = 0, k;while (scanf("%d", &num[i]) != EOF) {i++;}scanf("%d", &k); // 選擇第幾小的元素if( k > i)printf("error!\n");elseprint("%d\n", Select(0, i, k));return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的分治——线性时间选择算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。