二分

二分

二分查找是一种思路很简单,但是细节很复杂的算法。尤其是一些边界问题。使用二分需要确定一下两点:

整数二分

特点离散化,答案必在上述两个位置之一。

1.答案是红色区间的右端点

Q:为什么红线部分要加1?

A:这是由于除法会自动向下取整。例如:L=4 R=5 时,M = (4+5)/ 2 = 4=L,L = M = L,L、R永远不变,陷入死循环。

不加1:

加1:

2.答案是绿色区间的左端点

Q:为什么这里要补加1?

同理如下图:

小结

数字的范围

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 100000;

int n,q; 
int s[N+5];

int main(){
	scanf("%d%d",&n,&q);
	for (int i = 0; i < n; i ++ ) scanf("%d",&s[i]);
	while(q--)
	{
		int k = 0;
		scanf("%d",&k);
		int l = 0, r = n - 1;
		while(l < r)
		{
			int m = (l + r) / 2;
			if (s[m] >= k) r = m;
			else l = m + 1;
		}
		if (s[l] == k)
		   printf("%d ",l);
		else
		   printf("-1 -1\n");
                r = n - 1;
		while(l < r)
		{
			int m = l + r + 1 >> 1;
			if (s[m] <= k)
			   l = m;
			else r = m - 1;   
		}
		if (s[l] == k)
  		 printf("%d\n",l);	
	}
    return 0;
}

实数二分

数的三次方根

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

int main(){
	double n; 
	scanf("%lf",&n);
	double l = -10000,r = 10000;
	while (r - l > 1e-8 )
	{
		double mid = (l + r) / 2;
		if (mid * mid * mid >= n) r = mid;
		else l = mid; 
	}
	printf("%.6f",l);
    return 0;
}

习题

posted @ 2021-04-02 18:14  Treasure_lee  阅读(133)  评论(0)    收藏  举报