主要还是基于快排思想的二分查找 - 减治法:
- 分治法
分治法(Divide&Conquer),把一个大的问题,转化为若干个子问题(Divide),每个子问题“都”解决,大的问题便随之解决(Conquer)。这里的关键词是“都”。快速排序递归时,先通过partition把数组分隔为两个部分,两个部分“都”要再次递归。
分治法有一个特例,叫减治法。
- 减治法
减治法(Reduce&Conquer),把一个大的问题,转化为若干个子问题(Reduce),这些子问题中“只”解决一个,大的问题便随之解决(Conquer)。这里的关键词是“只”递归一个分支即可。
/*选出第K大的数*/
#include <iostream>
using namespace std;
int partition(int a[], int low, int high) //划分
{
int pivotKey = a[low];
while(low < high)
{
while(low < high && a[high] >= pivotKey)
{
high--;
}
a[low] = a[high];
while(low < high && a[low] <= pivotKey)
{
low++;
}
a[high] = a[low];
}
a[low] = pivotKey; //恢复
return low;
}
// 找第i个最小的值
int randomSelect(int *a, int low, int high, int i)
{
if(low == high)
{
return a[low];
}
int pivot = partition(a, low, high);
int k = pivot - low + 1;
if(k == i) // 刚好划出来了
{
return a[pivot];
}
if(i < k) // 缩小范围进行递归
{
return randomSelect(a, low, pivot - 1, i);
}
return randomSelect(a, pivot + 1, high, i - k); // 缩小范围进行递归
}
int main()
{
int a[] = {2, 5, 3, 1, 4, 111, 55};
int n = sizeof(a) / sizeof(a[0]);
int i = 6;
cout << randomSelect(a, 0, n - 1, i) << " " << endl; // 第i个最小值
return 0;
}