程序设计与算法(二):3. 二分算法

目录

例 查找p

例 查找lowerbound

例 二分法求方程的根

 例 找一对数

例 农夫和奶牛


例子源于慕课课程:程序设计与算法二

二分查找:有序、时间复杂度是log(n)

例 查找p

int BS(int a[], int size, int p) {
	int low = 0, high = size - 1;
	while (low <= high) {
		int mid = (low + high) / 2;

		if (a[mid] == p)
			return a[mid];
		else if (a[mid] < p) low = mid + 1;
		else high = mid - 1;
	}
	return -1;
}

例 查找lowerbound

代码

int BS(int a[], int size, int p) {
	int low = 0, high = size - 1;
	int lastposition = -1;//最优解的下标
	while (low <= high) {
		int mid = (low + high) / 2;
		if (a[mid] >= p)
			high = mid - 1;
		else {
			lastposition = mid;
			low = mid + 1;
		}
	}
	return lastposition;
}

注意

1. 从课程中学到mid=(low+high)/2有溢出的风险,可能(low+high)超出int的范围

2. 改成 mid=low+(high-low)/2;

3. 接下来取中点的代码都是改后的

例 二分法求方程的根

 

步骤是固定的

  • 确定单调性,本题是单调递增
  • 确定区间长度合适的有根区间,[0,100],f(0)<0,f(100)>0,root=(x1+x2)/2
  • 如果f(root)<0,新的区间为[root,x2]
  • 否则新的区间为[x1,root]
  • 注意只要得出满足精度条件(EPS=1e-6)的解即可

补充

1. fabs()函数:返回某一个值的绝对值的一个函数
例如,fabs(x)就是返回x的绝对值
2. fabs的参数为double型,返回值也是double型abs的参数为int型,返回值也是int型。
abs是求一个整数的绝对值,而fabs是求一个实数的绝对值。

代码

#define EPS 1e-6
double f(double x) { return x * x * x - 5 * x * x + 10 * x - 80; }

int main() {
	double x1 = 0, x2 = 100;
	double root = x1 + (x2 - x1) / 2;
	int cnt = 1;//记录尝试多少次
	double y = f(root);
	while (fabs(y) > EPS) {
		if ( f(root) > 0) 
			x2 = root;
		else 
			x1 = root;
		root = x1 + (x2 - x1) / 2;
		y = f(root);
		cnt++;
	}
	cout << "cnt=" << cnt << endl;
	printf("%.8f\n", root);
	return 0;
}

输出

 
例 找一对数

解法1:枚举,两重for循环,时间复杂度是O(n^2),本题规模大,n^2=100亿,OJ平台提交会超时

解法2:

  • 对数组排序,复杂度O(n*log(n) ) (排序用库函数)
  • 在数组中二分查找m-a[i],复杂度O(n*log(n) ),最坏查找n-2次
  • 总复杂度O(n*log(n) )

解法3:

  • 对数组排序,复杂度O(n*log(n) ) (排序用库函数)
  • 设置两个变量low,high,如果a[low]+a[high]<m,说明low小,low++;否则high大,high--,复杂度是O(n)
  • 总复杂度O(n*log(n) )

例 农夫和奶牛

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

跳坑坑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值