二分法

1、基于:分治策略
2、应用:有序序列
3、隐喻:二叉树
4、时间复杂度:O(logn)
5、关键字:scope


/**
* @param 数组a
* @param 目标值target
* @return 位序
*/
public static int binarySearch(int[] a, int target) {
int left = 0;
int right = a.length - 1; //游标

while (left <= right) //范围a[left:right]
{
int middle = (left + right) / 2; //取下整
if (target == a[middle])
return middle;
else if (target < a[middle])
right = middle - 1; //*明确边界
else
left = middle + 1; //*~
}
return -1;
}



关键点:
二分法算法描述简单,但关于scope的划分,边界的问题,理解透彻,对于别的类似问题就得心应手。

1、游标:
a[left:right] --闭区间,一个scope
2、下整:middle = (left+right)/2 --当scope变为2时,middle落在left上
3、闸门:while(left<=right)
若target不在a中,最后一次循环中左右游标交叉,则target在区间 (right,left)中。可以修改算法,返回right&left。
4、初始范围:a[0:n-1]
进入循环:a[left:right]
循环中,a[left:right]被分为三段:a[left:middle-1],a[middle],a[middle+1,right],边界要确保不重复,scope分明,就不会出现死循环。

每步while循环,scope都会缩小,最终会到达闸门left=right(或提前找到结果);
--算法会在有限步内终止 log(n)
并且确保target要在新的scope中。
--不会漏掉target


关键字:离散序列,连续序列


数学方面: --百度百科

一般地,对于函数f(x),如果存在实数c,当x=c时f(c)=0,那么把x=c叫做函数f(x)的零点。
  解方程即要求f(x)的所有零点。
  先找到a、b,使f(a),f(b)异号,说明在区间(a,b)内一定有零点,然后求f[(a+b)/2],
  现在假设f(a)<0,f(b)>0,a<b
  ①如果f[(a+b)/2]=0,该点就是零点,
  如果f[(a+b)/2]<0,则在区间((a+b)/2,b)内有零点,(a+b)/2=>a,从①开始继续使用
  中点函数值判断。
  如果f[(a+b)/2]>0,则在区间(a,(a+b)/2)内有零点,(a+b)/2=>b,从①开始继续使用
  中点函数值判断。
  这样就可以不断接近零点。
  通过每次把f(x)的零点所在小区间收缩一半的方法,使区间的两个端点逐步迫近函数的零点,以求得零点的近似值,这种方法叫做二分法。
  给定精确度ξ,用二分法求函数f(x)零点近似值的步骤如下:
  1 确定区间[a,b],验证f(a)·f(b)<0,给定精确度ξ.
  2 求区间(a,b)的中点c.
  3 计算f(c).
  (1) 若f(c)=0,则c就是函数的零点;
  (2) 若f(a)·f(c)<0,则令b=c;
  (3) 若f(c)·f(b)<0,则令a=c.
  4 判断是否达到精确度ξ:即若┃a-b┃<ξ,则得到零点近似值a(或b),否则重复2-4.

 例:(C语言)
  方程式为:f(x) = 0,示例中f(x) = 1+x-x^3
  使用示例:
  input a b e: 1 2 1e-5
  solution: 1.32472


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>

double f(double x){
return 1+x-x*x*x;
}
int main(){
double a=0,b=0,e=1e-5;
printf("input a b e:");
scanf("%lf%lf%lf",&a,&b,&e);
e=fabs(e);

if(fabs(f(a))<=e){
printf("solution:%lg\n",a);
}else if(fabs(f(b))<=e){
printf("solutionL:%lg\n",b);

}else if(f(a)*f(b)>0){
printf("f(%lg)*f(%lg)>0!need<=0!\n",a,b);
}else
{
while(fabs(b-a)>e){
double c=(a+b)/2.0;
if(f(a)*f(c)<0)
b=c;
else
a=c;
}
printf("solution:%lg\n",(a+b)/2.0);
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值