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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法设计与分析——递归与分治策略——线性时间选择

發(fā)布時間:2023/12/4 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法设计与分析——递归与分治策略——线性时间选择 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

顧名思義:這篇文章講解的就是如果用線性時間算法來作出元素選擇問題。
問題描述:給定線性序集中n個元素和一個整數k,1<=k<=n.要求找出這n個元素中第k小的元素,即如果將這個n個元素依其線性序排列時,排在第k個位置的元素就是要找的元素,當k== 1時,要找的就是最小的元素;當k==n,就是最大的元素;當k=(n+1)/2,稱為中位數。

問題分析:
在某些特殊的情況下,我們可以實現線性時間選擇,對于找最大最小的元素O(n)內可以實現;當k<=n/logn,通過堆排序算法可以在O(n+klogn)=O(n)內實現;當k>=n-n/logn時也一樣。
下面是給出的一般的選擇問題,從漸近階的意義上看,這個也可以在O(n)時間內完成。
下面的算法實現參考了《計算機算法與分析》和一些博客,是對其的一個整理。

方法一:
算法描述:用一個隨機的序列中的數作為樞紐,用快速排序算法,進行一次快排,然后將樞紐值和k值進行比較,以此來確定k值,我并沒有做任何的對比所以并不是清楚這種算法的效率有多少,但是搜到的結果表明,這種算法的最壞時間復雜度是O(n^2),相對與另一種是不太理想的。

解法:

1.首先大家都會想到的解法是排序,之后找出第k個元素,但是排序的時間復雜度不符合要求,或者需要額外的空間。

2.利用快排的思想,以樞紐(隨機得到)為界,將數組分為2部分,一部分小于等于這個樞紐值,一部分大于這個樞紐值,與快排不同的是,我們只處理一部分,另一部分舍棄。

#include<bits/stdc++.h> using namespace std;int partition(vector<int> &vec,int left,int right) {int i=left;int j=right;int temp=vec[left];while(i<j){while(vec[j]>=temp&&i<j)//處理i,j的先后順序不能改變 {j--;}while(vec[i]<=temp&&i<j){i++;}swap(vec[i],vec[j]);}vec[left]=vec[j];vec[j]=temp;return j; } int QuickSort(vector<int> &vec,int left,int right,int k) {if(left==right)return vec[left];int mid=partition(vec,left,right);int j=mid-left+1;if(k<=j)return QuickSort(vec,left,mid,k);elsereturn QuickSort(vec,mid+1,right,k-j);} void print(int x) {cout<<x<<" "; }int main() {vector<int> vec={1,2,3,6,5,4,7,8,9};for_each(vec.begin(),vec.end(),print);cout<<endl;int k;cout<<"請輸入K(要求找出這n個元素中第k小的元素):" ;cin>>k;int count=vec.size()-1;cout<<QuickSort(vec,0,count,k)<<endl;QuickSort(vec,0,count,k);for(auto a:vec){cout<<a<<" ";}cout<<endl;}


方法二:

這里我們就利用中位數來進行線性時間的選擇算法!

中位數就是指將數據按大小順序排列起來,形成一個數列,居于數列中間位置的那個數據就是中位數。

算法思路
(1)將輸入的n個數劃分成 ?n5??n5? 個組,當然最后一組的數目可能是小于5的!
(2)用任意的排序方法對他們進行排序,并取出一共 ?n5??n5? 個中位數。
(3)找出該 ?n5??n5? 個中位數中的中位數。(如果 ?n5??n5? 是偶數則取相對大的那個數)
(4)將全部的數劃分為兩個部分,小于基準的在左邊,大于等于基準的放右邊。

我們用小圓點表示元素,得到如下圖:

說明:
圖中中間白色圈表示各組數據的中位數,最中間灰色表示中位數的中位數! 箭頭是從較小的數指向較大的數!

故我們可以使用該數作為劃分的基準(比上一個隨機基準的方法會好很多)!

圖中

當n≥75時,3A1大于等于 14n14n。所以按此基準劃分所得的左右2個子數組的長度都至少縮短 1414。

#include<bits/stdc++.h> using namespace std;int partition(vector<int> &vec,int left,int right,int k) {int i=left;int j=right;int temp=vec[k];while(i<j){while(vec[j]>=temp&&i<j)//處理i,j的先后順序不能改變 {j--;}while(vec[i]<=temp&&i<j){i++;}swap(vec[i],vec[j]);}vec[k]=vec[j];vec[j]=temp;return j; }void print(int x) {cout<<x<<" "; }int Select(vector<int> &vec,int left,int right,int k) {if(right-left<75){return vec[left+k-1];}for(int i=0;i<=(right-left-4)/5;i++){}int x=Select(vec,left,left+(right-left-4)/5,(right-left-4)/10);int i=partition(vec,left,right,x);int j=i-left+1;if(k<=j)return Select(vec,left,i,k);elsereturn Select(vec,i+1,right,k-j);}int main() {vector<int> vec={1,2,3,6,5,4,7,8,9};for_each(vec.begin(),vec.end(),print);cout<<endl;int k;cout<<"請輸入K(要求找出這n個元素中第k小的元素):" ;cin>>k;int count=vec.size()-1;cout<<Select(vec,0,count,k)<<endl;Select(vec,0,count,k);for(auto a:vec){cout<<a<<" ";}cout<<endl;}

總結

以上是生活随笔為你收集整理的算法设计与分析——递归与分治策略——线性时间选择的全部內容,希望文章能夠幫你解決所遇到的問題。

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