首页 > 编程语言 >【计算机算法设计与分析】线性时间选择(C++_分治递归)

【计算机算法设计与分析】线性时间选择(C++_分治递归)

时间:2023-06-20 11:36:40浏览次数:74  
标签:分治 递归 int 元素 C++ 线性 flag swap 集合


问题描述

给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。

思路

线性时间选择有两种方法:
(1)随机选择快排的标准元素。
(2)将集合分为n个由五个元素组成的集合,对每个五元素集合求其中位数,再对所有的五元素集合的中位数求其中位数,作为快排的标准元素。

Code

V-1(RandomizedSelect)

#include<bits/stdc++.h>
#define M 100
using namespace std;
int a[M]={6, 7, 5, 2, 5, 8, 3, 5, 1};
int n=9;
int RandomizedPatition(int l, int r){
    srand((unsigned)time(NULL));
    int t=rand()%(r-l)+l;
    swap(a[t], a[l]);//随机元素作为标准
    int flag=a[l];
    while(l<r){
        while(l<r&&a[r]>=flag)
            r--;
        if(l<r){
            swap(a[r], a[l]);
        }
        while(l<r&&a[l]<=flag)
            l++;
        if(l<r){
            swap(a[r], a[l]);
        }
    }
    a[l]=flag;
    return l;

}
int RandomizedSelect(int l, int r, int k)
{
    if(l==r)
        return a[r]; 
    int p=RandomizedPatition(l, r);//将数组分成两部分
    int s=p-l+1;
    if(k<=s)
        RandomizedSelect(l, p, k);
    else{
        RandomizedSelect(p+1, r, k-s);
    }
    
}
int main()
{
    cout<<RandomizedSelect(0, n-1, 8);
    getchar();
    return 0;
}

V-2(Select)

#include<bits/stdc++.h>
#define M 1000
using namespace std;
int a[M]={3,1,7,6,5,9,8,2,0,4,13,11,17,16,15,19,18,12,10,14,23,21,27,26,25,29,28,22,20,24,33,31,37,36,35,39,38,32,30,34,43,41,47,46,45,49,48,42,40,44,53,51,57,56,55,59,58,52,50,54,63,61,67,66,65,69,68,62,60,64,73,71,77,76,75,79,78,72,70,74}, n=80;
void Sort(int l, int r){
    for(int i=l;i<=r;i++){
        for(int j=i+1;j<=r;j++){
            if(a[i]>a[j]){
                swap(a[i], a[j]);
            }
        }
    }
}
int partition(int l, int r){
    int flag=a[l];
    while(l<r){
        while(l<r&&a[r]>=flag)
            r--;
        if(l<r){
            swap(a[r], a[l]);
        }
        while(l<r&&a[l]<=flag)
            l++;
        if(l<r){
            swap(a[r], a[l]);
        }
    }
    a[l]=flag;
    return l;
}
int Select(int l, int r, int k){
    if(r-l+1<75){//小于75个直接冒泡排序即可
        Sort(l, r);
        return l+k-1;
    }
    for(int i=0;i<=(r-l-4)/5;i++){//55分组求中位数
        int temp=Select(l+5*i, l+5*i+4, 3);
        swap(a[temp], a[l+i]);
    }
    int s=Select(l, l+(r-l-4)/5, l+(r-l-4)/10);//找出中位数的中位数
    swap(a[s], a[l]);//交换至首位作为快排标准
    int p=partition(l, r);
    int t=p-l+1;//前半部分的元素个数
    if(k<=t){
        return Select(l, p, k);
    }else{
        return Select(p+1, r, k-t);
    }
}
int main()
{
    cout<<Select(0, n-1, 60)<<endl;
    getchar();
    return 0;
}


标签:分治,递归,int,元素,C++,线性,flag,swap,集合
From: https://blog.51cto.com/u_16165815/6521625

相关文章

  • 【剑指 Offer】用两个栈实现队列(C++_Easy_栈/队列)
    1.题目用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead操作返回-1)2.示例2.1示例1输入:[“CQueue”,“appendTail”,“deleteHead”,“deleteHead”......
  • 【计算机算法设计与分析】6-5 最小重量机器设计问题(C++_回溯法/分支限界法)
    问题描述设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设wij是从供应商j处购得的部件i的重量,cij是相应的价格。设计一个优先队列式分支限界法,给出总价格不超过d的最小重量机器设计。对于给定的机器部件重量和机器部件价格,设计一个优先队列式分......
  • 【蓝桥杯_真题演练】换零钞(C++_遍历)
    题目x星球的钞票的面额只有:100元,5元,2元,1元,共4种。小明去x星旅游,他手里只有2张100元的x星币,太不方便,恰好路过x星银行就去换零钱。小明有点强迫症,他坚持要求200元换出的零钞中2元的张数刚好是1元的张数的10倍,剩下的当然都是5元面额的。银行的工作人员有点为难,你能帮助算出:在满足小......
  • 【蓝桥杯_真题演练】第九届C/C++省赛B组_C-乘积尾零(C++_数论)
    Problem如下的10行数据,每行有10个整数,请你求出它们的乘积的末尾有多少个零?56504542355447394641143871907390432927587949611356595245743230514434670435949937117368663397475975573070228714539899148657223135117040145510512072928809......
  • PTA_乙级_1015 德才论(C++_模拟_快排)
    宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”现给出一批考生的德才分数,请根据司马光的理论给出录取排名。输入格式:输入第一行给出3个......
  • P3371 【模板】单源最短路径(弱化版)(C++_SPFA算法_链式向前星)
    题目背景本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步P4779。题目描述如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。输入格式第一行包含三个整数n,m,s,分别表示点的个数、有向边的个数、出发点的编号。接下来m行每行包含三个......
  • C++ primer plus学习之第二章
    1.引用:intival=1024;int&refval=ival;//正确,refval时ival的别名int&re;//错误,引用必须被初始化int&ii=42;//错误:不能为非常量引用绑定字面值constint&ii=42;//正确:可以为常量引用绑定字面值2.初始化空指针int*p=0;int*p=NULL;int*p=nullptr;//最好用这个任何非零指......
  • abc044d <根号分治>
    https://atcoder.jp/contests/abc044/tasks/arc060_b//https://atcoder.jp/contests/abc044/tasks/arc060_b//根号分治//将数据范围分为两部分处理,使得拆开成两部分后各部分复杂度均符合要求#include<iostream>#include<algorithm>#include<cmath>usingnamespace......
  • 代码随想录算法训练营第十二天| 递归遍历 (必须掌握)迭代遍历 统一迭代
    递归遍历重点:1,TreeNode的自定义2,val=0== val=NULL;代码:1voidpreRecursor(TreeNode*root,vector<int>&result)2{3if(root==NULL)4return;5result.push_back(root->val);6preRecursor(root->left,result);7......
  • 总结C++中#include<>和#include""的区别
    查找目录不同1、#include<>编译器直接从系统类库目录里查找头文件比如在vs中,使用#include<>编译器会直接在vs安装目录下在编译器自带的库文件中进行搜索。如果类库目录下查找失败,编译器会终止查找,直接报错:Nosuchfileordirectory.如果我们自定义一个头文件"aaa.h",将其放在......