二分查找
概念
二分查找是一个基础的算法,也是面试中常考的一个知识点。二分查找就是将查找的键和子数组的中间键作比较,如果被查找的键小于中间键,就在左子数组继续查找;如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素。
理解
二分查找的过程是区间【left,right】向目标target逼近的过程,区间逐渐缩短,最终区间会缩为一个点或right == left +1的小区间。
二分查找算法的前提是数组有序(升序,降序等)。
-
数组的二分查找。
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
将target与mid进行对比,如果mid等于target,返回索引;如果mid大于target,right=mid-1;如果mid小于target,left=mid+1,因为不一定能搜索到,查找条件为left≤right。
int search(vector<int>& nums, int target) { int n=nums.size(); int mid; int left= 0; int right= n-1; while(left<=right) { mid = (right- left)/2 + left; if(nums[mid] == target) return mid; nums[mid]<target ? left= mid +1:right= mid -1; } return -1; }
-
第一个错误的版本。
数组由 0 和 1 组成,前面的元素为 0,后面的元素为 1,求第一个元素 1的下标(已知数组的最后一个元素是1)。例如,[0,0,0,0,1,1,1,1,1],[0,0,…,0,111,111]等
将mid进行判断,如果mid等于1,right=mid(考虑到mid可能是target,将mid仍然放在下次查找区间内);如果等于0,left=mid+1。因为一定能查找到,所以查找条件为left < right。
```cpp
int firstBadVersion(int nums,int n) {
int left = 1, right = n;
while (left < right)
{
int mid = left + (right - left) / 2; // 防止计算时溢出
if (nums[i]) {
right = mid; // 答案在区间 [left, mid] 中
} else {
left = mid + 1; // 答案在区间 [mid+1, right] 中
}
}
// 此时有 left == right,区间缩为一个点,即为答案
return left;
}
```
-
搜索插入的位置。
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
将target与mid进行对比,如果mid等于target,返回索引;如果mid大于target,right=mid-1;如果mid小于target,left=mid+1,因为不一定能搜索到,查找条件为left≤right。跳出while循环时,right==left-1(left前插入)或left ==right+1(left后插入)。
#include <vector> #include <iostream> using namespace std; int searchInsert(vector<int>& nums,int target){ int mid,left,right; left = 0; right = nums.size() - 1; while(left<=right){ mid = (right - left)/2 + left; if(nums[mid] == target){ return mid; } nums[mid] > target ? right = mid - 1 : left = mid + 1; } return left; //left就是插入的位置 } int main(int argc, char const *argv[]) { vector<int> nums{1,2,3,4,5,6}; int j; int i = 7; j = searchInsert(nums,i); return 0; }