学习笔记:二分法

问题引入:
给定一个按照升序排列的长度为n的整数数组,询问元素k,返回k在数组中的起始位置和终止位置。
如果数组中不存在该元素,则返回“-1 -1”。
例如:
6 3
1 2 2 3 3 4

则应返回4 5

二分最重要的一步是区间划分,即确定左区间表示什么,右区间表示什么,然后确定是输出l还是r
对于本题,
求起始位置时,可以让>=k的元素划分到右区间,最后起始位置start=r
求终止位置时,可以让<=k的元素划分到左区间,最后终止位置end=l

const int N = 1e5+5;

int n,a[N];

int main()
{
    
    
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++)	cin>>a[i];

	int start,end;
	int l=0,r=n+1;//一开始让l指针与r指针指在待划分区间[1,n]的两侧
	while(l+1!=r)
	{
    
    
		int mid=(l+r)/2;
		if(a[mid]>=k)	r=mid;
		else	l=mid;
	}
	start=r;
	l=0,r=n+1;
	while(l+1!=r)
	{
    
    
		int mid=(l+r)/2;
		if(a[mid]<=k)	l=mid;
		else	r=mid;
	}
	end=l;
	if(start<=end)	cout<<start<<" "<<end<<endl;
	else	cout<<-1<<" "<<-1<<endl;
	return 0;
}

浮点数的二分:
给定一个浮点数x(-10000<=x<=10000),求它的三次方根。(结果保留6位小数)

int main()
{
    
    
	double x;	cin>>x;
	
	double l=-100-1,r=100+1;
	while(r-l>1e-7)//注意精度问题,此处最少要1e-7
	{
    
    
		double mid=(l+r)/2;
		if(mid*mid*mid>=x)	r=mid;
		else	l=mid;
	}
	printf("%.6lf\n",l); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_50815157/article/details/113446123