一、二分法查找
「二分查找」通过不断缩小搜索区间的范围,直到找到目标元素或者没有找到目标元素。这里「不断缩小搜索区间」是一种 减而治之 的思想,也称为减治思想。
二分查找算法的应用范围:
在有序数组中进行查找一个数(二分下标)
在整数范围内查找一个整数(二分答案)
二分查找算法的两种思路
- 思路 1:在循环体中查找元素
- 思路 2:在循环体中排除目标元素一定不存在的区间
public class Solution {
// 「力扣」第 704 题:二分查找
public int search(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len - 1;
// 目标元素可能存在在区间 [left, right]
while (left <= right) {
// 推荐的写法是 int mid = left + (right - left) / 2;
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
// 目标元素可能存在在区间 [mid + 1, right]
left = mid + 1;
} else {
// 目标元素可能存在在区间 [left, mid - 1]
right = mid - 1;
}
}
return -1;
}
}
作者:liweiwei1419
链接:https://leetcode-cn.com/leetbook/read/learning-algorithms-with-leetcode/xsz9zc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
编码要点
循环终止条件写成:while (left < right) ,表示退出循环的时候只剩下一个元素;
在循环体内考虑如何缩减待搜索区间,也可以认为是在待搜索区间里排除一定不存在目标元素的区间;
根据中间数被分到左边和右边区间,来调整取中间数的行为;
如何缩小待搜索区间,一个有效的办法是:从 nums[mid] 满足什么条件的时候一定不是目标元素去考虑,进而考虑 mid 的左边元素和右边元素哪一边可能存在目标元素。一个结论是:当看到 left = mid 的时候,取中间数需要上取整,这一点是为了避免死循环;
退出循环的时候,根据题意看是否需要单独判断最后剩下的那个数是不是目标元素。
边界设置的两种写法:
right = mid 和 left = mid + 1 和 int mid = left + (right - left) / 2; 一定是配对出现的;
right = mid - 1 和 left = mid 和 int mid = left + (right - left + 1) / 2; 一定是配对出现的。