1.线性时间选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素(这里给定的线性集是无序的)。
/*************************************************************************
> File Name: 2.cpp
> Author: mazicwong
> Mail: mazicwong@gmail.com
> Created Time: 2017年10月08日 星期日 14时01分00秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <time.h>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
using namespace std;
//Partition功能: 通过基准元素a[p]对子数组a[p..r]进行划分
template<class Type>
int Partition(Type a[],int p,int r)
{
int i=p,j=r+1;
Type x = a[p];
while(1)
{
while(a[++i]<x && i<r);
while(a[--j]>x);
if (i>=j) break;
swap(a[i],a[j]);
}
swap(a[j],a[p]);//j处元素还是小于p处的,换一下
return j;
}
//产生[p,r]间的随机数
template<class Type>
Type Random(Type p,Type r)
{
srand(time(NULL));
Type del = r-p;
return rand()%del+p;
}
//Partition的改进,用来产生随机划分
template<class Type>
int RandomizedPartition(Type a[],int p,int r)
{
int i=Random(p,r);//产生[p,r]间的随机数
swap(a[i],a[p]);
return Partition(a,p,r);
}
//随机快速排序
template<class Type>
void RandomizedQuickSort(Type a[],int p,int r)
{
if(p<r)
{
int q = RandomizedPartition(a,p,r);
RandomizedQuickSort(a,p,q-1); //排序左半段
RandomizedQuickSort(a,q+1,r); //排序右半段
}
}
//线性第k小算法
template<class Type>
Type RandomizedSelect(Type a[],int p,int r,int k)
{
if (p==r) return a[p];
int i = RandomizedPartition(a,p,r);
int j = i-p+1;
if (k<=j) return RandomizedSelect(a,p,i,k);
else return RandomizedSelect(a,i+1,r,k-j);
}
int a[10] = {2,4,5,7,6,9,8,1,10,3};
void io()
{
cout << "数组: ";
for (auto i:a)
cout << i << ' ';
cout << endl;
}
int main()
{
//freopen("in","r",stdin);
io();
int k;
while(cin>>k)
{
int ans = RandomizedSelect(a,0,9,k);
cout << "第k小是: " << ans << endl;
}
return 0;
}
2.给定由n个互不相同的数组成的集合S以及正整数k<=n,试设计一个O(n)时间算法找出S中最接近S的中位数的k个数。
/*************************************************************************
> File Name: 2.cpp
> Author: mazicwong
> Mail: mazicwong@gmail.com
> Created Time: 2017年10月08日 星期日 14时01分00秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <time.h>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
using namespace std;
//Partition功能: 通过基准元素a[p]对子数组a[p..r]进行划分
template<class Type>
int Partition(Type a[],int p,int r)
{
int i=p,j=r+1;
Type x = a[p];
while(1)
{
while(a[++i]<x && i<r);
while(a[--j]>x);
if (i>=j) break;
swap(a[i],a[j]);
}
swap(a[j],a[p]);//j处元素还是小于p处的,换一下
return j;
}
//产生[p,r]间的随机数
template<class Type>
Type Random(Type p,Type r)
{
srand(time(NULL));
Type del = r-p;
return rand()%del+p;
}
//Partition的改进,用来产生随机划分
template<class Type>
int RandomizedPartition(Type a[],int p,int r)
{
int i=Random(p,r);//产生[p,r]间的随机数
swap(a[i],a[p]);
return Partition(a,p,r);
}
//随机快速排序
template<class Type>
void RandomizedQuickSort(Type a[],int p,int r)
{
if(p<r)
{
int q = RandomizedPartition(a,p,r);
RandomizedQuickSort(a,p,q-1); //排序左半段
RandomizedQuickSort(a,q+1,r); //排序右半段
}
}
//线性第k小算法
template<class Type>
Type RandomizedSelect(Type a[],int p,int r,int k)
{
if (p==r) return a[p];
int i = RandomizedPartition(a,p,r);
int j = i-p+1;
if (k<=j) return RandomizedSelect(a,p,i,k);
else return RandomizedSelect(a,i+1,r,k-j);
}
//以上: 线性选择第k小
//以下: 找中位数临近k个数
int a[11] = {2,77,66,11,100,0,10,99,1000,1111,2000};
void io()
{
cout << "数组: ";
for (auto i:a)
cout << i << ' ';
cout << endl;
cout << "排序后: ";
int ans[11]; for (int i=0;i<11;i++) ans[i]=a[i];
sort(ans,ans+11);
for (auto i:ans) cout << i << ' ';
cout << " 用来做对比" << endl;
}
typedef pair<int,int> pii;
pii del[11];
int main()
{
//freopen("in","r",stdin);
io();
int num=11;
int mid = RandomizedSelect(a,0,num-1,(num+1)/2);
//for(int i=0;i<num;i++) cout << a[i] << ' ';cout<<endl;
cout << "中位数是: " << mid << endl;
for (int i=0;i<num;i++) del[i].first=abs(a[i]-mid),del[i].second=i;
int deltmp[11];for(int i=0;i<11;i++)deltmp[i]=del[i].first;
int k;cout<<"输入k: ";
while(cin>>k)
{
int ansTmp = RandomizedSelect(deltmp,0,num-1,k);
for (int i=0;i<num;i++)
if (del[i].first<=ansTmp)
cout << a[del[i].second] << ' ';
cout << endl << endl << "输入k: ";
}
return 0;
}