二分算法理解:
二分是一种我们十分熟知的算法,在很多的地方都有着神奇的用处,在各大比赛上都是很有用的工具性算法
我们可以把二分理解成是一种不断缩小答案范围最后找到解的算法,但是需要注意的是,他的实现是在数据有序的基础上实现的
假设我们现在有着这样一组数据
10
1 2 3 4 5 6 7 8 9 10
要寻找 3 的位置
二分法的思路便是这样的:
①取出最中间的数即是 5 ,以及寻址空间 1~10
3 比 5 小,所以是在 5 的左边的,由此寻址空间便变化为 1~4
②取出中间的数 2 (寻址空间 1~4 )
3 比 2 大 ,所以是在 2 的右边,由此寻址空间变化为 3~4;
③取出中间数 3 (寻址空间 3~4)
3 == 3 ,找到解了
PS:我们的范围是上一次中间数向前减 1 ,或向前加 1 的,这样不会重复,避免取出错误的中间数
这是很容易去理解的,代码也很容易去记住以及理解,但是二分答案的难点是在对答案是否合法,以及边界的判断上,我们很需要注意的
二分算法实现
非递归法
这种方法是以while循环来实现的
代码:
int main()
{
///输入
//sort(a+1,a+n+1); 注意,一定是要有序的!!!
left = 1; //取最小的,即是第一个(常理下都是升序的)
right = n; //最大的
while (left <= right) //判断是否还有寻址空间
{
mid = (left + right) / 2; //去中间数的下标
if (a[mid] == k) break; //可以理解成边界,也就是找到解的下标了
//没找到的情况
if (a[mid] < k) right = mid + 1; //①在答案的左边,缩小寻址空间
if (a[mid] > k) left = mid - 1; //②在答案的右边,缩小寻址空间
}
cout<<mid; ///输出答案的下标
}
递归法实现
递归的也是很好理解的,但是代码相较上面的用while来实现的要难记住一些,两种方法是个有千秋的,在不同的题型上,不同的方式有不同的优点,这是需要我们来分析的,也是在做题的过程中需要注意的
代码:
int get(int left,int key,int right) //几个形参,left是左边到哪儿,key是要查找的关键字,right是右边到哪儿
{
int mid = (left + right) / 2; //取中间数的下标
if (left > right) return -1; //边界①:无解
if (a[mid] == key) return mid; //边界②:找到解
//下面两个对范围的断定和上面while的性质一样,只是用递归来实现罢了
if (a[mid] < key) return get(mid+1,key,right);
if (a[mid] > key) return get(left,key,mid-1);
}
int main()
{
输入;
ans = get(1,k,n); //输入范围,用ans来存下标
cout<<ans;
}
总结
二分是一种速度快的飞起的算法,好了,88
二分查找是一种很有用的工具,在很多地方能做到很大的用处,我们要加强对其的练习,在赛场上可以熟练准确的敲出来
** 菜鸡c_uizrp_dzjopkl原创**