0.二分法简介
  • 二分法是一种查找算法
  • 要求:数据必须是有序序列
  • 核心思想:掐头去尾取中间

1. 引入

对于一个有序数组,如{1,3,6,8,23,56,78,99},如果我们要查找其中的一个数78的下标位置,按照以前的写法,可能会这么写

#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
	int a[]={1,3,6,8,23,56,78,99},target;// 定义数组和要查找的目标 
	int len= sizeof(a)/sizeof(int);
	cin>>target;
	for(int i=0;i<len;i++)
	{
	 	if(a[i]==target)
	 		{
				cout<<i<<endl;
				return 0; 
			}
	} 
	return 0;
} 

这种顺序查找的方式对于数据量较小的情况还可以应付,但是对于数据量大的情况就很难处理了。试想一下特殊情况,如果你要查找的值正好在数组的最后一个,那么你的时间复杂度就是O(n)。所以引入二分查找来解决这个问题。

640?

640?

如果上面的题目用二分法求解,可以参考下面代码。(题目保证有解的情况下)

#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
	int a[]={1,3,6,8,23,56,78,99},target;// 定义数组和要查找的目标 
	int len,left,right,mid;//定义长度,左端点,右端点,中间 
	right = sizeof(a)/sizeof(int); //右端点 
	left=0; //左端点 
	mid=(left+right)/2;  //中间 
	cin>>target;
	while(a[mid] !=target)
	{
		if(a[mid] > target)
			right=mid;
		else
			left = mid;
		mid=(left+right)/2;	
	} 
	cout<<mid;
	
	return 0;
} 

2.二分法求解
例题1

【描述】给定一个排序的整数数组(升序)和一个要查找的整数target,找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1【输入描述】输入包含三行,第一行n,表示有n个数,第二行是已经排好序的n个数
第三行是target【输出描述】一行,target第一次出现的下标,如果没有找到输出-1。【样例输入1】
6
1 4 6 7 9 11
4【样例输出1】
1【样例输入2】
7
1 2 6 8 9 12 78
4【样例输出1】
-1


【注意】题目不一定有解,可以遵循下面的算法框架

while (left < right - 1) {
	int mid = left + (right - left) / 2;
	//添加结束条件 
	
	// 
	if (A[mid] > A[left]) {
		left = mid;
	} else {
		right = mid;
	}
}


【参考代码】

#include<cstdio>
#include<iostream>
using namespace std;
int search(int A[], int n, int target)  
{  
    int left = 0, right = n-1;  
    while(left <= right)  
    {  
        // 注意:若使用(low+high)/2求中间位置容易溢出  
        int mid = left+((right-left)>>1);   
        if(A[mid] == target)  
            return mid;  
        else if(A[mid] < target)  
            left = mid+1;  
        else // A[mid] > target  
            right = mid-1;  
    }  
    return -1;  
}  
int main()
{
	int a[100]={0},target;// 定义数组和要查找的目标
	int len,n,index;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];	
	}	
	cin>>target;
	index = search(a,n,target); 
	cout<<index;
	return 0;
} 

例题2

【描述】给定一个有序(非降序)数组A,可含有重复元素,求最大的i使得A[i]等于target,不存在则返回-1【输入描述】输入包含三行,第一行n,表示有n个数,第二行是已经排好序的n个数
第三行是target【输出描述】一行,target最后一次出现的下标,如果没有找到输出-1。


返回目录:算法


分类: 算法