介绍

BFPRT是解决求一个数组中第K小的数的算法,可以时间O(N)的时间复杂度,而使用排序求第K小的数的算法的时间复杂度为O(NlogN),因此BFPRT算法更加高效

思想

(1)分组:将原数组每五个数分为一组,不足5个数的单分一组
(2)组内排序:每个小组从小到大进行排序
(3)选取每个分组中的中位数组成一个中位数数组
(4)求中位数数组的中位数
(5)将第四步求出的中位数作为划分值,对原数组进行划分,小于的放左边,等于的放中间,大于的放右边

getMid函数

组内排序,并返回该组的中位数

int getMid(int arr[], int begin, int end){sort(arr+begin,arr+end+1);return arr[begin + (end - begin)/2];
}

midOfMids函数

实现分组,生成中位数数组,并返回中位数数组的中位数

int midOfMids(int arr[], int begin, int end){int size = end-begin+1;int groupSzie = (size - 1) / 5 + 1;int *midArr = new int[groupSzie];int L = begin;int R = L + 4 > end ? end : L + 4;for(int i = 0; i < groupSzie; i++){midArr[i] = getMid(arr, L, min(R, end));L = R + 1;R = L + 4 > end ? end : L + 4;}return bfprt(midArr, 0, groupSzie-1, groupSzie/2);

partition函数

按照k值对数组进行划分

int *partition(int arr[], int begin, int end, int k){int L = begin-1;int R = end+1;int cur = begin;while(cur < R){if(arr[cur] < k){swap(arr, ++L, cur++);}else if(arr[cur] == k){cur++;}else{swap(arr, --R, cur);}}return new int [2] {L + 1, R - 1};
}

bfprt函数

实现整个流程,没有单独调用midOfMids,直接在函数体内实现

int bfprt(int arr[], int begin, int end, int k){if(begin == end)return arr[begin];int size = end - begin + 1;int groupSzie = (size - 1) / 5 + 1; //向上取整int *midArr = new int[groupSzie];int L = begin;int R = L + 4 > end ? end : L + 4;for(int i = 0; i < groupSzie; i++){midArr[i] = getMid(arr, L, min(R, end));L = R + 1;R = L + 4 > end ? end : L + 4;}int midNum = bfprt(midArr, 0, groupSzie - 1, groupSzie/2);int *p = partition(arr, begin, end, midNum);if(k < p[0])return bfprt(arr, begin, p[0] - 1, k);else if(k > p[1])return bfprt(arr, p[1] + 1, end, k);return arr[k];
}

完整代码

#include <iostream>
#include <algorithm>
using namespace std;void swap(int arr[], int i, int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}int *partition(int arr[], int begin, int end, int k){int L = begin-1;int R = end+1;int cur = begin;while(cur < R){if(arr[cur] < k){swap(arr, ++L, cur++);}else if(arr[cur] == k){cur++;}else{swap(arr, --R, cur);}}return new int [2] {L + 1, R - 1};
}int getMid(int arr[], int begin, int end){sort(arr+begin,arr+end+1);return arr[begin + (end - begin)/2];
}int bfprt(int arr[], int begin, int end, int k){if(begin == end)return arr[begin];int size = end - begin + 1;int groupSzie = (size - 1) / 5 + 1; //向上取整int *midArr = new int[groupSzie];int L = begin;int R = L + 4 > end ? end : L + 4;for(int i = 0; i < groupSzie; i++){midArr[i] = getMid(arr, L, min(R, end));L = R + 1;R = L + 4 > end ? end : L + 4;}int midNum = bfprt(midArr, 0, groupSzie - 1, groupSzie/2);int *p = partition(arr, begin, end, midNum);if(k < p[0])return bfprt(arr, begin, p[0] - 1, k);else if(k > p[1])return bfprt(arr, p[1] + 1, end, k);return arr[k];
}int main()
{int n, k;cin >> n >> k;int *arr = new int[n];for(int i = 0; i < n; i++)cin >> arr[i];cout << bfprt(arr, 0, n-1, k-1) << endl;return 0;
}

测试代码

使用sort函数,即使用排序的方法求第K小的数,然后随机生成一个一维数组,找第K小的数,与BFPRT算法进行比较,以测试BFPRT算法的正确性

#include <iostream>
#include <algorithm>
using namespace std;void swap(int arr[], int i, int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}int *partition(int arr[], int begin, int end, int k){int L = begin-1;int R = end+1;int cur = begin;while(cur < R){if(arr[cur] < k){swap(arr, ++L, cur++);}else if(arr[cur] == k){cur++;}else{swap(arr, --R, cur);}}return new int [2] {L + 1, R - 1};
}int getMid(int arr[], int begin, int end){sort(arr+begin,arr+end+1);return arr[begin + (end - begin)/2];
}int bfprt(int arr[], int begin, int end, int k){if(begin == end)return arr[begin];int size = end - begin + 1;int groupSzie = (size - 1) / 5 + 1; //向上取整int *midArr = new int[groupSzie];int L = begin;int R = L + 4 > end ? end : L + 4;for(int i = 0; i < groupSzie; i++){midArr[i] = getMid(arr, L, min(R, end));L = R + 1;R = L + 4 > end ? end : L + 4;}int midNum = bfprt(midArr, 0, groupSzie - 1, groupSzie/2);int *p = partition(arr, begin, end, midNum);if(k < p[0])return bfprt(arr, begin, p[0] - 1, k);else if(k > p[1])return bfprt(arr, p[1] + 1, end, k);return arr[k];
}int randSize;//生成随机数组
template <class T>
T* creatArr(int size, int value){//srand((unsigned)time(NULL));srand(rand());randSize = rand()%(size+1)+1;T *arr = new T [randSize];for(int i = 0; i < randSize; i++){arr[i] = rand()%(value+1) - rand()%(value+1);cout << arr[i] << " ";}cout << endl;return arr;
}//输出数组
template<class T>
void outputArr(T arr[], int size){for(int i = 0; i < size; i++){cout << arr[i] << " ";}cout << endl;
}//拷贝数组
template<class T>
T* copyArr(T arr[], int size){T* newArr = new T [size];for(int i = 0; i < size; i++){newArr[i] = arr[i];}return newArr;
}int main(){int testTime = 50000;int size = 10, value = 1000;while(testTime--){int *arr = creatArr<int>(size, value);srand(rand());int k = rand() % randSize + 1;int my = bfprt(arr, 0, randSize-1, k-1);sort(arr, arr+randSize);int res = arr[k-1];if(my != res){cout << "Error!" << endl;break;}else{cout << "Nice!" << endl;}}
}

第K小的数BFPRT算法相关推荐

  1. python递归算法 电影院票价问题_算法课堂实验报告(二)——python递归和分治(第k小的数,大数乘法问题)...

    python实现递归和分治 一.开发环境 开发工具:jupyter notebook 并使用vscode,cmd命令行工具协助编程测试算法,并使用codeblocks辅助编写C++程序 编程语言:py ...

  2. 算法导论:快速找出无序数组中第k小的数

    题目描述: 给定一个无序整数数组,返回这个数组中第k小的数. 解析: 最平常的思路是将数组排序,最快的排序是快排,然后返回已排序数组的第k个数,算法时间复杂度为O(nlogn),空间复杂度为O(1). ...

  3. 分治算法求解列表中第k小的数

    分治算法地思想就是将复杂问题分解为简单的子问题,然后寻求子问题的地归结,并组合各个子问题的解一起得到最终复杂问题的解. 针对求解列表中第k小的数,暴力拆解法可以将列表排序然后根据索引求出列表中第k小的 ...

  4. 7-1 找第k小的数(反思),a++和++a的区别,运算符优先级,递归分制思想

    作者 陈晓梅 单位 广东外语外贸大学 设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数. 提示 函数int partition(int a[],i ...

  5. 在两个已经排好序的数组里找出第K小的数

    前言: 这道题是一道非常常见的面试题,也是一道能够考察一个人的编程能力和算法的一道题.如果要求复杂度为 O(k), 是比较容易做出来的,但是,一般来讲,面试官要求给出更低复杂度的算法.网上有很多不同的 ...

  6. 7-1 找第k小的数 (20 分)

    设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数. 提示:函数int partition(int a[],int left,int right)的 ...

  7. 在数组中找到第 k 小的数

    在数组中找到第 k 小的数 [要求] 如果 arr 长度为 N,要求时间复杂度为 O(N),额外空间复杂度为 O(1). public static int[] getMinKNumByHeap(in ...

  8. html5数组查找第二大数,2021-06-29:在两个都有序的数组中找整体第K小的数。

    2021-06-29:在两个都有序的数组中找整体第K小的数. 福大大 答案2021-06-29: 1.A和B长度不等的时候,需要把A和B的长度变成相等. A是短数组,B是长数组. 第k小的数,k从1开 ...

  9. 面试题:找两个有序数组所有数第K小的数

    给定两个有序数组arr1和arr2,再给定一个整数k,返回两个数组中所有数中第k小的数.要求:如果arr1的长度为N,arr2的长度为M,时间复杂度请达到O(log(min{M, N}) ) 例如: ...

最新文章

  1. mpvue生命周期初探
  2. cam db num
  3. c c和java最大的区别是什么,“一般”和“一般”之间的区别是什么,类型在C ++和Java?...
  4. 关注手机病毒:重点手机安全事件盘点
  5. 【Leetcode】1818.绝对差值和
  6. 【随文杂想】超长图PS 切片为打印机 A4纸大小打印
  7. ONOS 南向抽象层分析
  8. 纯RAW数据转换为DNG格式
  9. python爬取网易云音乐飙升榜音乐_python爬取网易云音乐热歌榜 python爬取网易云音乐热歌榜实例代码...
  10. Windows下的SSL 应用
  11. 数据治理的数据流程整合
  12. 中台之上:商业银行业务架构设计
  13. python做爬虫选课_Python2爬虫:以爬取大学本学期绩点为例(实战)
  14. 人工神经网络的算法原理,神经网络算法的原理是
  15. 关于节日文化的HTML网页设计-----二十四节气
  16. IDEA设置todo快捷键
  17. 抱歉,您的 Microsoft 帐户出现问题。请转到 https://account.live.com 寻求帮助”
  18. c语言笔记本无法读取鼠标,USB鼠标失灵了怎么办 电脑无法识别USB鼠标【详解】...
  19. 攻防世界-pwn-forgot
  20. EVT, DVT, MVT, PVT常见软件节点是什么意思

热门文章

  1. 客户故事:4家银行如何打造新一代移动金融中心 1
  2. 标书制作视频教程入门到精通-《标书制作特训营》
  3. 2021年电工(初级)及电工(初级)考试试题
  4. 如何从零启动做公众号引流,分享公众号引流的8个有效方法
  5. 给你的Excel增加正则处理函数,简直如虎添翼
  6. 基于电力线载波的路灯控制系统设计
  7. 回飞锅有哪些功能_很多人问BK回飞锅怎么保养?现在放上一些自己的心得
  8. C#:实现数字是否为3的倍数(附完整源码)
  9. linux电子设计软件,集成电路eda软件
  10. ps怎样将图片转为html5,Photoshop中,“点”与“像素”如何相互转换、换算?