线性选择序列第k小 / 中位数附近k个数

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值