有序条件下,才能查找
一.二分查找
(具有单调性,不一定严格单调)
(min 与max 是查找区间,通过不断缩小查找区间,来查找x的值)
min是头指针; max是尾指针;mid = (min + max) / 2;
终止条件:min >= max
如果arr[mid] < x, min = mid + 1;
如果arr[mid] > x, max = mid - 1;
如果arr[mid] == x, 找到结果
1.特殊情况(求最小最大解)
查找最后的1
【min】【1】【1】【1】【1】【1】【0】【0】【0】【0】【0】
mid max
min:虚拟头指针
max:尾指针
mid = (min + max + 1) / 2
调整:
如果arr[mid] == 1, min = mid
如果arr[mid] != 1, max = mid - 1
如果min==max, 找到结果
2.特殊情况(求最小花费)
查找第一个1
【0】【0】【0】【0】【1】【1】【1】【1】【1】【1】【max】
min mid
min:头指针
max:虚拟尾指针
mid = (min + max) / 2
调整:
如果arr[mid] == 1,min = mid + 1;
如果arr[max] != 1, max = mid;
如果min==max,找到结果
二.三分查找
每次搜索范围缩小三分之一
求凹凸函数的极值问题
在二分查找的基础上,在右区间(或左区间)再进行一次二分,这样的查找算法称为 三分查找,也就是三分法。
三分查找通常用来迅速确定最值。
(1)mid = (left + right) / 2;
(2)取右侧区间的中间值midmid,把区间分为三个小区间;midmid = (mid + right) / 2;
(3)比较mid与midmid谁最靠近最值,只需要确定mid所在的函数值与midmid所在的函数值的大小。当最值为最大值时,mid与midmid中较大的那个自然更为靠近最值。最值为最小值时同理。
#include <stdio.h>
#include <math.h>
int binary_search1(int *num, int n, int x){
int min = 0, max = n - 1, mid;
while(min <= max){
mid = (min + max) / 2;
if(num[mid] == x) return mid;
if(num[mid] < x) min = mid + 1;
else max = mid - 1;
}
return -1;
}
int binary_search2(int *num, int n){//找到最后的1,Eg:11111000
int min = -1, max = n - 1, mid;//min是虚拟头指针;
while(min < max){
mid = (min + max + 1) / 2;//+1防止出现min与mid重合的死循环;
if(num[mid] == 0) max = mid - 1;//由于要找的是1,可以把后面的数据都扔掉了;
else min = mid;
}
return min;//找不到自动等于-1;
}
int binary_search3(int *num, int n){//找到第一个1,Eg:00011111
int min = 0, max = n, mid;//max是虚拟尾指针,防止出现死循环;
while(min < max){
mid = (min + max) / 2;
if(num[mid] == 0) min = mid + 1;//由于要找数据1,可以把前面的数据扔掉了;
else max = mid;
}
if(min == n) return -1;//数组中没有1;
return min;
}
double f(double x){
static double a = 3.0, b = 2.0, c = 1.0;
return a * x * x + b * x + c;
}
double ternary_search(double (*func) (double)){
#define EPSLON 1e-7
double L = -1000, R = 1000, m1, m2;
while(fabs(L - R) > EPSLON){
m1 = (R - L) / 3.0 + L;
m2 = 2.0 * (R - L) / 3.0 + L;
if(func(m1) > func(m2)) L = m1;
else R = m2;
}
#undef EPSLON
return L;
}
int main(){
int num1[] = {1, 2, 3, 4, 5, 6};
printf("binary_search1(5): %d\n", binary_search1(num1, 6, 5));
int num2[] = {1,1,1,1,1,1,1,1,0,0,0,0,0,0,0};
printf("binary_search2(last one): %d\n", binary_search2(num2, 15));
int num3[] = {0,0,0,0,0,0,0,1,1,1,1,1,1,1,1};
printf("binary_search3(first one): %d\n", binary_search3(num3, 15));
printf("ternary_search(): %lf\n", ternary_search(f));
return 0;
}
输出结果:
binary_search1(5): 4
binary_search2(last one): 7
binary_search3(first one): 7
ternary_search(): -0.333333