C++实现查找中位数的O(N)算法和Kmin算法

yizhihongxing

C++实现查找中位数的O(N)算法和Kmin算法

中位数

  • 中位数指的是一组数据中间位置的数。
  • 对于一组无序数据而言,可以使用快速排序、堆排序等算法求出其中位数。
  • 但是这些算法的时间复杂度较高。
  • 在此讨论的是时间复杂度为O(N)的算法。

O(N)算法

  • O(N)算法的基本思想:将一组数据分成若干组,然后对于每一组进行处理。
  • 首先随机选择一个数作为参考数,然后将数据分为两组,一组比参考数小,另一组比参考数大。
  • 此时有三种情况:
  • 分组后小于参考数的组中元素个数等于N/2,则中位数为参考数;
  • 小于参考数的组中元素个数小于N/2,在大于参考数的组中递归搜索中位数;
  • 小于参考数的组中元素个数大于N/2,在小于参考数的组中递归搜索中位数。

  • 通过以上三种情况,可以保证每次递归后搜索的数据量都会减半,实现了O(N)的时间复杂度。

#include<bits/stdc++.h>
using namespace std;

int nums[100005];

// 搜索中位数
int searchmid(int l,int r,int k){
    if(l+1>=r)return nums[l];
    int i=l+1,j=r-1,x=nums[l];
    while(i<j){
        while(nums[i]<=x && i<j)i++;
        while(nums[j]>x)j--;
        if(i<j)swap(nums[i],nums[j]);
    }
    if(nums[l]<nums[j-1])swap(nums[l],nums[j-1]);
    else{
        j--;
        swap(nums[l],nums[j]);
    }
    if(j-l==k)return nums[j];
    if(j-l>k)return searchmid(l,j,k);
    else return searchmid(j,r,k-j+l);
}

int main(){
    // 读入数据
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++)cin>>nums[i];
    // 搜索中位数
    int ans=searchmid(0,n,k);
    // 输出结果
    cout<<ans<<endl;
    return 0;
}

Kmin算法

  • Kmin算法的目标是查找一组数据中第K小的数据。
  • 思路为沿用O(N)算法的分组思路,对于每一组确定其最小值$min_l$和最大值$max_r$,找到一组数,使其小于或等于$max_r$,大于或等于$min_l$,则其中必然包含第K小的数。
#include<bits/stdc++.h>
using namespace std;

int nums[100005];

// 寻找第k小的数
int searchkmin(int l,int r,int k){
    if(l+1>=r)return nums[l];
    int m=rand()%(r-l)+l;
    swap(nums[m],nums[l]);
    int i=l+1,j=r-1,x=nums[l];
    while(i<j){
        while(nums[i]<=x && i<j)i++;
        while(nums[j]>x)j--;
        if(i<j)swap(nums[i],nums[j]);
    }
    if(nums[l]<nums[j-1])swap(nums[l],nums[j-1]);
    else{
        j--;
        swap(nums[l],nums[j]);
    }
    if(j-l==k)return nums[j];
    if(j-l>k)return searchkmin(l,j,k);
    else return searchkmin(j,r,k-j+l);
}

int main(){
    // 读入数据
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++)cin>>nums[i];
    // 寻找第k小的数
    int ans=searchkmin(0,n,k);
    // 输出结果
    cout<<ans<<endl;
    return 0;
}

示例

示例一

输入:

5 3
3 4 2 5 1

输出:

3

说明:

查找第三小的数。

分组后:小于2的数组合为{1},大于2的数组合为{3,4,5}。

小于2的数组合包含0个第三小的数,需要在大于2的数组合中查找第三小的数。

分组后:小于4的数组合包含3个数,大于4的数组合包含1个数。

小于4的数组合中第三小的数位于大于4的数组合中,继续查找第三小的数。

分组后:小于3的数组合中包含两个数,等于3的数组合中包含一个数。

查找结束,找到的第三小的数为3。

示例二

输入:

7 5
-1 2 -2 5 10 -5 4

输出:

2

说明:

查找第五小的数。

分组后:小于$-2$的数组合为$-5$,等于$-2$的数组合为空,大于$-2$的数组合为$-1,2,5,10,4$。

小于$-2$的数组合包含0个第五小的数,需要在大于$-2$的数组合中查找第五小的数。

分组后:小于$4$的数组合包含4个数,大于$4$的数组合包含2个数。

小于$4$的数组合中包含第五小的数,继续查找第五小的数。

分组后:小于$2$的数组合为$-1,-2$,等于$2$的数组合为空,大于$2$的数组合为$5,10$。

小于$2$的数组合包含3个第五小的数,需要在大于$2$的数组合中查找第$5-3=2$小的数。

分组后:小于$5$的数组合包含2个数,等于$5$的数组合包含一个数。

查找结束,找到的第五小的数为2。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现查找中位数的O(N)算法和Kmin算法 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C语言利用goto语句设计实现一个关机程序

    下面是关于利用goto语句设计实现一个C语言关机程序的完整攻略: 1.了解goto语句 对于C语言程序员而言,goto语句可能是一种被大家所忽略的语法结构。goto语句可以让程序跳转到代码的标签位置处执行,这个特性可以被用于令程序从中间跳转到代码的其他位置,或者跳出多层循环嵌套等场所。 goto语句的基本语法结构如下: goto label; 其中,”lab…

    C 2023年5月23日
    00
  • C语言实现超市计价收款系统

    C语言实现超市计价收款系统攻略 简介 本文将介绍如何使用C语言实现一个简单的超市计价收款系统。该系统将能够记录商品信息、价格以及计算顾客的购物总价等功能。 主要步骤 以下是实现该系统的主要步骤: 定义结构体 定义商品信息的结构体,包括商品名、价格等信息。例如: struct goods { char name[20]; int price; int num;…

    C 2023年5月23日
    00
  • C++制作《游戏内存外挂》详解

    C++制作《游戏内存外挂》详解 简介 本文介绍如何使用 C++ 制作游戏内存外挂,以及外挂原理和相关技术。 前置知识 C++ 语言基础 内存读写基础 操作系统基础知识 制作思路 找到目标游戏的进程 ID 或句柄 获取目标游戏进程的基址(或模块地址) 根据内存地址偏移量,访问和读取或写入指定内存地址的值 设计以及实现内存操作功能(读/写) 实现示例 1:内存读…

    C 2023年5月22日
    00
  • C/C++ Qt 数据库与ComBox实现多级联动示例代码

    首先,我们要明确一下本文的目标,即通过C/C++ Qt编写代码实现数据库和ComBox的多级联动。下面是实现步骤和示例说明。 步骤一:建立数据库连接 我们需要使用Qt提供的QSqlDatabase类来建立与数据库的连接。在连接前,我们还需要确定数据库的类型和属性,例如,数据库的名称、主机名、用户名、密码等。以下是建立数据库连接的示例代码: QSqlDatab…

    C 2023年5月22日
    00
  • C语言访问特殊用途的地址

    我来详细讲解一下C语言访问特殊用途的地址的完整使用攻略。 什么是特殊用途地址 特殊用途地址(Special Purpose Address)是指在计算机系统中被用于特定目的的内存地址。在C程序中,可以通过这些地址来访问一些系统资源,如输入输出端口、内存映射设备等。 常见的特殊用途地址包括两种:物理地址和虚拟地址。物理地址是指直接映射到物理内存的地址,而虚拟地…

    C 2023年5月10日
    00
  • C语言如何利用ASCII码表统计字符串每个字符出现的次数

    如何利用ASCII码表统计字符串每个字符出现的次数? 初始化计数数组 首先,我们需要使用C语言定义一个计数数组。该数组用于存储ASCII码表中每一个字符出现的次数。由于ASCII码表中总共有128个字符,所以我们需要定义一个长度为128的数组。需要注意的是,数组中每一个元素的初始值都应该为0。 int count[128] = {0}; 遍历字符串 接下来,…

    C 2023年5月23日
    00
  • Android App调试内存泄露之Cursor篇

    Android App调试内存泄露之Cursor篇 什么是内存泄露 Android应用程序中常见的问题是内存泄漏问题。内存泄漏指的是程序中的对象在使用完之后仍然被占用并未得到垃圾回收,导致内存空间不断被占满,从而引发ANR和崩溃等问题。 Cursor泄露的原因 在Android开发中,我们使用Cursor对象进行数据的操作。Cursor对象是一种轻量级的数据…

    C 2023年5月23日
    00
  • C++算法系列之日历生成的算法代码

    首先,这篇文章介绍了如何用 C++ 编写一个生成日历的算法。该算法基于一个假设:为了表示一个月的日历,我们只需要知道该月的第一天是星期几,和该月的天数。因此,我们可以先确定出每个月的第一天是星期几,然后再以此为基础,生成整个月的日历。 在代码实现方面,我们可以使用 C++ 的结构体来存储一个日期,并为它提供一些常用的方法,例如获取下一个日期、判断两个日期是否…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部