每次在做二分查找的题目的时候,如果target的值不存在于待查找数组中,边界条件我老写错。
今天来总结下,希望自己能完全攻克这类问题。
该算法的核心思想就是:首先二分查找只能应用在已经有序的数组中,通过每次折半的缩小查找范围直到找到目标元素,若查找范围为1还没找到则说明,待查元素不存在于该有序数组中。
在写二分查找的时候一定要明确查找范围,并且在写代码的过程中始终保持一致。
704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
1 | 输入: nums = [-1,0,3,5,9,12], target = 9 |
示例 2:
1 | 输入: nums = [-1,0,3,5,9,12], target = 2 |
提示:
- 你可以假设
nums中的所有元素是不重复的。 n将在[1, 10000]之间。nums的每个元素都将在[-9999, 9999]之间。
模板1
1 | class Solution { |
模板2
1 | class Solution { |
二分查找衍生出的两个重要函数
STL中二分查找的函数有 3 个(头文件为: #include
1 |
|
lower_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个 出现的位置。
功能:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置.返回的是是一个迭代器,所以要求下标位置的话还需要用返回值减去起始地址.
注意:如果所有元素都小于val,则返回last的位置,且last的位置是越界的!
upper_bound(起始地址,结束地址,要查找的数值) 返回的是 第一个大于待查找数值 出现的位置。
功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置
注意:返回查找元素的最后一个可安插位置,也就是“元素值 > 查找值”的第一个元素的位置。同样,如果val大于数组中全部元素,返回的是last。(注意:数组下标越界)。返回的是是一个迭代器,所以要求下标位置的话还需要用返回值减去起始地址。
binary_search(起始地址,结束地址,要查找的数值) 返回的是是否存在这么一个数,是一个bool值。
lower_bound() 的实现
为了实现方便,我们直接传入一整个数组,并且返回值为下标而不是像STL是迭代器类型.
1 | int lower_bound(vector<int>& nums, int target) { |
upper_bound() 的实现
1 | int upper_bound(vector<int>& nums, int target) { |
注意: 二分查找的题目细节是魔鬼,一定要明白自己是在哪个范围里找目标,并且每次在缩小查找范围的时候一定要保证与开始定的范围一样,若开始是全闭区间则缩小了查找范围也一定是全闭区间,若开始是半闭半开区间则缩小了查找范围也一定是半闭半开区间。