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

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语言实现任务调度的示例代码

    我来讲解一下如何利用C语言实现任务调度的示例代码。 什么是任务调度 任务调度是指按照一定规则和策略,将多个任务分配给CPU或其他的计算资源。通过任务调度,不同的任务可以在合适的时候被处理,从而提高系统的效率和稳定性。 使用C语言实现任务调度的示例 下面,我将给出一个使用C语言实现任务调度的示例代码: #include <stdio.h> #inc…

    C 2023年5月22日
    00
  • C语言学生成绩管理系统源码

    C语言学生成绩管理系统源码完整攻略 源码下载 首先,我们需要从Github上下载C语言学生成绩管理系统的源代码。在Github上搜索关键词C语言学生成绩管理系统即可找到相应的项目。 下载完成后,我们可以得到以下几个文件: main.c:程序主函数 student.h:定义了student结构体以及相关函数的头文件 student.c:实现了student结构…

    C 2023年5月23日
    00
  • C++中vector的用法实例解析

    C++中vector的用法实例解析 什么是vector vector是C++ STL(Standard Template Library)中的一个容器,它是一个动态数组,可以自动扩展空间,并提供随机访问和快速尾部插入/删除等操作。vector内部存储的元素在内存中是连续存储的,因此可以通过数组下标直接访问元素,效率非常高。 vector的基本用法 创建一个v…

    C 2023年5月22日
    00
  • 如何用C写一个web服务器之CGI协议

    我们来详细讲解如何用C写一个Web服务器并支持CGI协议。 什么是CGI协议? CGI(通用网关接口)是一种标准,定义了外部程序和Web服务器之间的接口规范。通过CGI程序,Web服务器可以调用位于其它服务器上的应用程序或资源。 编写CGI程序的步骤 1.确定Web服务器的CGI目录。通常默认为cgi-bin目录,如果不知道可以查看服务器配置文件。 2.在C…

    C 2023年5月23日
    00
  • 详解C++编程中断言static_assert的使用

    详解C++编程中断言static_assert的使用 在C++中,当我们需要在编译期进行类型检查或常量计算时,可以使用static_assert。具体来说,static_assert是一个语言特性,用于在编译期进行断言判断,如果判断条件为false,则程序会在编译期抛出一个编译错误,阻止程序的继续编译。 用法 static_assert可以用于两种类型的判断…

    C 2023年5月23日
    00
  • C++中的对象数组详细解析

    C++中的对象数组详细解析 什么是对象数组 对象数组是指由多个相同类型的对象依次排列组成的数组。在 C++ 中,一个对象数组一旦被定义,就会在内存中分配相应的空间,同时数组名也被定义为一个指向该数组首元素的指针。 定义一个对象数组示例: class Person { public: Person(string name, int age) { this-&g…

    C 2023年5月22日
    00
  • C++实现图书管理系统简易版

    C++实现图书管理系统简易版攻略 前言 图书管理系统是一种基础的管理系统,它可以帮助管理员管理图书信息和读者信息,完成借阅、归还等基本操作。本文将详细介绍如何使用C++编程实现图书管理系统的简易版。 实现步骤 1. 确定需求 在编写代码之前,需要明确所要实现的功能需求。基本需求如下: 管理员可以添加图书和删除图书 管理员可以添加读者和删除读者 读者可以查询图…

    C 2023年5月24日
    00
  • C++实现闹钟程序的方法

    下面我来详细讲解一下 C++ 实现闹钟程序的方法。 一、实现思路 要实现闹钟程序,就需要先了解一下闹钟程序的基本功能:1)设置闹钟时间;2)定时器到时后发出提示音;3)停止提示音。根据这些功能,我们可以分解出以下几个步骤: 读取用户设置的闹钟时间; 判断当前时间是否等于闹钟时间,如果不等待,则继续等待; 定时器到时后,播放提示音; 用户选择关闭提示音或延迟提…

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