bfprt算法

bfprt算法及其相关

找到无序数组中最小的K个数

【题目】

给定一个无序的整型数组arr,找到其中最小的k个数。

【要求】

如果数组arr的长度为N,排序之后自然可以得到最小的k个数,此时时间复杂度为排序的时间复杂度即O(N*logN)。本题要求读者实现时间复杂度O(N*logK)和O(N)的方法。

利用堆:

public int[] getMinKNumsByHeap(int[] arr, int k) {

if (k < 1 || k > arr.length) {

return arr;

}

int[] kHeap = new int[k];

for (int i = 0; i != k; i++) {

heapInsert(kHeap, arr[i], i);

}

for (int i = k; i != arr.length; i++) {

if (arr[i] < kHeap[0]) {

kHeap[0] = arr[i];

heapify(kHeap, 0, k);

}

}

return kHeap;

}

public void heapInsert(int[] arr, int value, int index) {

arr[index] = value;

while (index != 0) {

int parent = (index - 1) / 2;

if (arr[parent] < arr[index]) {

swap(arr, parent, index);

index = parent;

} else {

break;

}

}

}

public void heapify(int[] arr, int index, int heapSize) {

int left = index * 2 + 1;

int right = index * 2 + 2;

int largest = index;

while (left < heapSize) {

if (arr[left] > arr[index]) {

largest = left;

}

if (right < heapSize && arr[right] > arr[largest]) {

largest = right;

}

if (largest != index) {

swap(arr, largest, index);

} else {

break;

}

index = largest;

left = index * 2 + 1;

right = index * 2 + 2;

}

}

public void swap(int[] arr, int index1, int index2) {

int tmp = arr[index1];

arr[index1] = arr[index2];

arr[index2] = tmp;

}

利用bfprt算法:

public int[] getMinKNumsByBFPRT(int[] arr, int k) {

if (k < 1 || k > arr.length) {

return arr;

}

int minKth = getMinKthByBFPRT(arr, k);

int[] res = new int[k];

int index = 0;

for (int i = 0; i != arr.length; i++) {

if (arr[i] < minKth) {

res[index++] = arr[i];

}

}

for (; index != res.length; index++) {

res[index] = minKth;

}

return res;

}

public int getMinKthByBFPRT(int[] arr, int K) {

int[] copyArr = copyArray(arr);

return select(copyArr, 0, copyArr.length - 1, K - 1);

}

public int[] copyArray(int[] arr) {

int[] res = new int[arr.length];

for (int i = 0; i != res.length; i++) {

res[i] = arr[i];

}

return res;

}

public int select(int[] arr, int begin, int end, int i) {

if (begin == end) {

return arr[begin];

}

int pivot = medianOfMedians(arr, begin, end);

int[] pivotRange = partition(arr, begin, end, pivot);

if (i >= pivotRange[0] && i <= pivotRange[1]) {

return arr[i];

} else if (i < pivotRange[0]) {

return select(arr, begin, pivotRange[0] - 1, i);

} else {

return select(arr, pivotRange[1] + 1, end, i);

}

}

public int medianOfMedians(int[] arr, int begin, int end) {

int num = end - begin + 1;

int offset = num % 5 == 0 ? 0 : 1;

int[] mArr = new int[num / 5 + offset];

for (int i = 0; i < mArr.length; i++) {

int beginI = begin + i * 5;

int endI = beginI + 4;

mArr[i] = getMedian(arr, beginI, Math.min(end, endI));

}

return select(mArr, 0, mArr.length - 1, mArr.length / 2);

}

public int[] partition(int[] arr, int begin, int end, int pivotValue) {

int small = begin - 1;

int cur = begin;

int big = end + 1;

while (cur != big) {

if (arr[cur] < pivotValue) {

swap(arr, ++small, cur++);

} else if (arr[cur] > pivotValue) {

swap(arr, cur, --big);

} else {

cur++;

}

}

int[] range = new int[2];

range[0] = small + 1;

range[1] = big - 1;

return range;

}

public int getMedian(int[] arr, int begin, int end) {

insertionSort(arr, begin, end);

int sum = end + begin;

int mid = (sum / 2) + (sum % 2);

return arr[mid];

}

public void insertionSort(int[] arr, int begin, int end) {

for (int i = begin + 1; i != end + 1; i++) {

for (int j = i; j != begin; j--) {

if (arr[j - 1] > arr[j]) {

swap(arr, j - 1, j);

} else {

break;

}

}

}

}

public void swap(int[] arr, int index1, int index2) {

int tmp = arr[index1];

arr[index1] = arr[index2];

arr[index2] = tmp;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 23:19:42

bfprt算法的相关文章

查找第K小的数 BFPRT算法

BFPRT算法是解决从n个数中选择第k大或第k小的数这个经典问题的著名算法,但很多人并不了解其细节.本文将首先介绍求解这个第k小数字问题的几个思路,然后重点介绍在最坏情况下复杂度仍然为O(n)的BFPRT算法. 一 基本思路 关于选择第k小的数有许多方法 将n个数排序(比如快速排序或归并排序),选取排序后的第k个数,时间复杂度为O(nlogn). 维护一个k个元素的最大堆,存储当前遇到的最小的k个数,时间复杂度为O(nlogk).这种方法同样适用于海量数据的处理. 部分的快速排序(快速选择算法)

快速排序以及堆排序在查找数方面的主要应用 即将引出线性查找BFPRT算法

<span style="font-size: 13.3333px;"><span style="font-size: 13.3333px;">应用解释:要求找出一组数中的第n大的数字</span></span> <span style="font-size: 13.3333px;">1.快速排序改进-1(快速选择算法)</span><p style="fon

BFPRT(线性查找算法)

BFPRT算法解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,通过巧妙的分 析,BFPRT可以保证在最坏情况下仍为线性时间复杂度.该算法的思想与快速排序思想相似,当然,为使得算法在最坏情况下,依然能达到o(n)的时间复杂 度,五位算法作者做了精妙的处理. 算法步骤: 1. 将n个元素每5个一组,分成n/5(上界)组. 2. 取出每一组的中位数,任意排序方法,比如插入排序. 3. 递归的调用selection算法查找上一步中所有中位数的中位数,设为x,偶数个中位数的情况下设定

BFPRT线性查找算法

介绍: BFPRT算法解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,通过巧妙的分 析,BFPRT可以保证在最坏情况下仍为线性时间复杂度.该算法的思想与快速排序思想相似,当然,为使得算法在最坏情况下,依然能达到o(n)的时间复杂 度,五位算法作者做了精妙的处理. 时间复杂度 O(N) 算法步骤: 1. 将n个元素每5个一组,分成n/5(上界)组. 2. 取出每一组的中位数,任意排序方法,比如插入排序. 3. 递归的调用selection算法查找上一步中所有中位数的中位数,设

线性查找算法(BFPRT)

BFPRT算法的作者是5位真正的大牛(Blum . Floyd . Pratt . Rivest . Tarjan). BFPRT解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,通过巧妙的分析,BFPRT可以保证在最坏情况下仍为线性时间复杂度. 步骤 将n个元素每 5 个一组,分成n/5(上界)组. 取出每一组的中位数,任意排序方法,比如插入排序. 递归的调用 selection 算法查找上一步中所有中位数的中位数,设为x,偶数个中位数的情况下设定为选取中间小的一个. 用x

动态展示十大经典算法

算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序n个项目要Ο(nlogn)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(nlogn)算法更快,因为它的内部循环(innerloop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divideandconquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1.从数列中挑出一个元素,称为“基准”(pivot),

程序员必须知道的10大基础实用算法及其讲解

程序员必须知道的10大基础实用算法及其讲解 原文出处: cricode 算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比 较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构 上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子

程序员必知的10大基础实用算法

    算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2) 次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的 架构上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1 从数列中挑出一个元

十大编程算法助程序员走上高手之路

算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1 从数列中挑出一个元素,称为 "