1.算法介绍
1.基本思路介绍
二分法:二分查找算法是一种在有序数组中查找某一特定元素的搜索算法,其思想就是不断地将有序查找表“一分为二”,逐渐缩小搜索区域,进而找到目标元素。
搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;
如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,跟开始一样从中间元素开始比较。
如果在某一步骤数组为空,则代表找不到。
2.复杂度
因为二分查找每一次查找都可以缩减掉一半的查找范围,由此可以知道二分查找法的时间复杂度是:Ο(logn)。
若这里一共有2^32个元素,那么我在最坏的情况下也只需要32次就可以找到我想找的元素;而顺序查找法最坏的情况下,却需要查找 4,294,967,296 次!!!,可见二分查找法的效率是非常之高的。
注:使用二分查找的前提条件是,数组已经是有序的
2.红蓝染色
1.为什么使用该方法
二分可以解决问题的共同点
数组中存在一条分界线,使得分界线左边的位置都满足某个条件并且右边的位置都不满足同一个条件。
接着我们要找到一条分界线,满足分界线左边的数字都 < x,右边的数字都 >= x
所以现在有一个疑问:分界线怎么找?
一开始,分界线一定是在序列的两个边界,如果数组从1开始存储的话,那么分界线就在0和n + 1的位置;如果数组从0开始存储的话,那么分界线就在-1和n的位置。
经过上面的思路理解,我们应该看出来二分查找算法的基本路径;
但是在实际敲代码中,我们会发现
1.二分查找的边界值很难掌控,经常乱作一团。
2.l,r的值变换什么加加减减的非常麻烦
需要去记忆什么 左闭右闭区间,左闭右开区间两种写法。
故而使用一种新的方法,红蓝染色法;
思路来源于:b站up主 五点七边
2.红蓝染色法基本思路介绍
left指针掌管左边蓝色区域,蓝色表示 true即所求值及其右侧,right指针掌管右边红色区域,红色表示false即所求值左侧,
两者互不冲突,通过不断向目标区域靠近,扩大两个指针的掌管区域,直到两者掌管的区域接壤
使用闭区间时,L-1必定是红色即false,R+1必定是蓝色即true,这就是循环不变量
关键不在于区间里的元素具有什么性质,而是区间外面的元素具有什么性质,即将区间外染成红色与蓝色。
根据以上两点,在做题时关键即确定二分条件函数isBlue(),判断是否满足条件,满足条件则right 左移使右侧变蓝 ,不满足条件则left 右移使左侧变红
3.代码思路
1.开始时,left和right指针指向探索的区域之外,即left指向探索区域的首元素下标-1,right指向探索区域的尾元素+1
2.循环条件为left+1!=righ,当left+1==right时,结束循环,此时蓝红区域划分完毕,区域均已着色
3.mid值始终为 (left+right)//2
4.left和right指针变化时,直接变成mid,无需+1或-1
5.最后根据需求返回left或者right即可
对于 ifblue 函数的选取,我们需要根据题目来决定,但是重要的一点是,只要我们记住红蓝两区域互斥,就可以比较轻松解决这个问题
4.伪代码
数组为
我们对于l与r的选取需要在数组之外,这是因为
如果整个数组都是蓝色,那么如果让r初始化为最后一个元素,则r一开始就存在于蓝色区域中,无法排除最后一个元素。
5.扩充
这个模板确实不用去记+1-1的情况,而且大多数的边界问题处理的都非常好,但是当target 在对应的数组中没有出现的时候,这个方法就会有问题。
此时可以在return前面增加代码判断一下元素。
if(arr[right] != check)
{
return -1;
}
else return right;