算法设计与分析之线性时间选择(C++)
算法設計與分析之線性時間選擇
- 線性時間選擇算法
- 例題一
- 問題描述
- 問題分析
- 算法實現
- 例題二
- 問題描述
- 問題分析
- 算法實現
- 本博客其他文章推薦
線性時間選擇算法
- 模仿快速排序算法
- 對數組使用分治策略
例題一
問題描述
對于給定的n個元素的數組a[0:n—1],要求從中找出第k小的元素
輸入:輸入有多組測試例。
?對每一個測試例有2行
?第一行是整數n和k(1≤k<n≤1000)
?第二行是n個整數
輸出:第k小的元素
問題分析
我們知道,快速排序算法的一次排序的思想是:
?找到一個數字作為標準,把比該數小的放左邊,比該數大的放右邊
要找到第k小的元素,最粗暴的就是全部排序,但這樣做了很多多余的工作,借鑒快速排序算法的一次排序思想,我們可以以數組首位元素作為一個標準,把小于它的放左邊,大于它的放右邊:
- 當這個標準左邊的元素和它加起來為k的話,就找到第k小的數了
- 當這個標準左邊的元素和它加起來小于k的話,就向右邊繼續找第(k-1-該數下標)小的數
- 當這個標準左邊的元素和它加起來大于k的話,就向左邊繼續找第k小的數
算法實現
#include <iostream> #include <algorithm> #define N 100 using namespace std; //一維數組容器 int a[N];//線性選擇算法尋找第k小的元素 int linearTimeSelection(int,int,int);int main() {int n,k;cout<<"輸入數組大小:";cin>>n;if(n>N || n<1) {cout<<"預留空間不足或數組大小非法!";exit(0);}cout<<"輸入數組元素:";for(int i=0;i<n;i++) cin>>a[i];cout<<"查找第幾小的元素:";cin>>k;if(k > n || k < 1){cout<<"查找位置非法!";exit(0);}cout<<linearTimeSelection(0,n-1,k);return 0; } /*left 進行線性選擇的首位下標right 進行線性選擇的末尾下標k 尋找第k位小的元素 */ int linearTimeSelection(int left,int right,int k){if(left >= right) return a[left];int point = a[left];int i = left,j = right+1;while(1){do{i++;}while(a[i] < point);do{j--;}while(a[j] > point);if(i>=j) break;swap(a[i],a[j]);}if(j-left+1 == k) return point;a[left] = a[j];a[j] = point;if(j-left+1 < k) return linearTimeSelection(j+1,right,k-(j+1-left)); //向右找return linearTimeSelection(left,j-1,k); //向左找 }例題二
問題描述
??某石油公司計劃建造一條由東向西的主輸油管道。該管道要穿過一個有n口油井的油田。從每口油井都要有一條輸油管道沿最短路經(或南或北)與主管道相連。
??如果給定n口油井的位置,即它們的x坐標(東西向)和y坐標(南北向),編程計算各油井到主管道之間的輸油管道最小長度總和。
輸入
??第1行是一個整數n,表示油井的數量(1≤n≤10 000)
??接下來n行是油井的位置,每行兩個整數x和y(-10 000≤x,y≤10 000)
輸出
??各油井到主管道之間的輸油管道最小長度總和
輸入樣例
5
1 2
2 2
1 3
3 -2
3 3
輸出樣例
6
樣例圖
問題分析
- 如何確定主輸油管道位置?
由上面我對輸入樣例畫出的分析圖,可以清晰的看到這個主管道只由y坐標確定位置,而且主管道存在于y值的值域內(即所輸入的y坐標的最大最小值之間),因為要找油井到主管道間的距離和最小,所以找到油井位置的y值的中位數即可。 - 如何計算最小距離和?
找到主管道位置后,我們對每個油井都計算到主管道的距離,加起來即可 - 關于中位數求法
1、直接排序,找n/2下標的元素;
2、使用線性時間選擇算法選擇第n/2小的元素;(我們使用這種方法)
算法實現
#include <iostream> #include <algorithm> #define N 10000 using namespace std;//存儲油井的y值 int a[N]; //線性時間選擇算法 int linearTimeSelection(int,int,int); int main() {int n,temp;cout<<"請輸入油井的數量:";cin>>n;cout<<"請輸入油井坐標:";for(int i=0;i<n;i++)cin>>temp>>a[i];//主管道位置int mid = linearTimeSelection(0,n-1,n/2);int sum = 0;for(int i=0;i<n;i++){sum += abs(a[i]-mid);}cout<<sum<<endl;return 0; }int linearTimeSelection(int left,int right,int k){if(left >= right) return a[left];int i = left,j = right+1;int point = a[left];while(1){do{i++;}while(a[i]<point);do{j--;}while(a[j]>point);if(i>=j) break;swap(a[i],a[j]);}if(j-left+1 == k) return point;a[left] = a[j];a[j] = point;if(j-left+1 < k) return linearTimeSelection(j+1,right,k-(j-left+1));return linearTimeSelection(left,j-1,k); }本博客其他文章推薦
算法設計與分析之分治策略練習(下)
算法設計與分析之分治策略練習(上)
算法設計與分析之分治策略
算法設計與分析之遞歸算法練習(下)
算法設計與分析之遞歸算法練習(上)
總結
以上是生活随笔為你收集整理的算法设计与分析之线性时间选择(C++)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hp-ux 单用户 启动_UX备忘单:搜
- 下一篇: 前端学习(2930):内嵌改变样式