前言
练习了一些关于二分查找的leetcode的题,总结一下。
使用二分查找时的场景为有序数组,或直接给你一个数字但同时会给你一个有序区间(在接下来的leetcode题中就是这种场景)。总之就是有序的集合。
二分查找算法的3个角色
left
左指针right
右指针mid
由左右指针所包围的区间内的中心
概念
二分查找的过程其实就是收缩左右指针的区间的过程。我们根据实际情况选择将左指针右移或者右指针左移,以及它们移动的步长,这是编写二分查找指针的重点和难点。
总结即可用四个字概括:滑动窗口,只不过每次可以滑动当前窗口的一半的距离。
解决leetcode问题:x 的平方根
在有了以上的知识基础,我觉得可以解决接下来的问题了。
class Solution {
public int mySqrt(int x) {
//特殊情况特殊处理
if (x == 1) return 1;
//参数1:场景 参数2:左指针 参数3:右指针
return get(x, 0, x);
}
//二分查找算法
public int get(int x, int left, int right) {
//重点:结束递归条件,也是结束二分查找需满足的条件(根据实际情况设置)
if (right - 1 == left) return left;
//获取区间中心
int mid = (right - left) / 2 + left;
//重点:根据不同的情况收缩区间,或者若是直接找到了所求值,直接返回即可
long tmp = (long) mid * mid;
if (tmp == x) return mid;
else if (tmp > x) right = mid;
else left = mid;
//递推下去,直到满足条件
return get(x, left, right);
}
}
注意事项
以上的解决方案,笔者在有些地方踩了坑。
如:
//我们应该尽可能这样写
int mid = (right - left) / 2 + left;
//而不是
int mid = (left + right) / 2;
//原因:第二种写法容易造成溢出。
//这里笔者曾经粗心过
long tmp = mid * mid;
//正确写法如下
long tmp = (long) mid * mid;