算法解释:二分查找也常被称为二分法或者折半查找,每次查找时通常将区间分为两部分,并只取一部分进行查找。将查找的复杂度大大较少。
具体到代码上,二分查找时区间的左右端取开区间还是闭区间在绝大多数时候都可以,因此有些初学者会容易搞不清楚如何定义区间开闭性。这里我提供两个小诀窍,第一是尝试熟练使用一种写法,比如左闭右开或左闭右闭,尽量只保持一种写法;第二是在刷题时思考如果最好区间只剩下一个数或者两个数,自己的写法是否会陷入死循环,如果某种写法无法跳出死循环,则尝试考虑另外一种写法。
二分查找也可以看做双指针的一种特殊情况,但我们一般会将二者区分。双指针类型的问题,指针通常是一步一步移动的,而在二分查找里,指针每次移动半个区间长度。
1、求开方 leetcode69
题目描述:给定一个非负数,求它的开方,向下取整。
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int MySart(int& a) {
if (a == 0) {
return 0;
}
int l = 1;
int r = a;
int mid = 0, sqrt = 0;
while (l < r) {
mid = l + (r-1) / 2;
sqrt = a / mid;
if (sqrt == mid) {
return sqrt;
}
else if (mid > sqrt) {
r = mid -1;
}
else {
l = mid;
}
}
return r;
}
void main() {
int input = 10;
cout << "thr value sqrt is :" << MySart(input) << endl;
cout << "hello world" << endl;
}
2、旋转数组查找数字 leetcode 81题
题目描述:
一个原本增序的数组被首尾相连后按某个位置断开(如[1,2,2,3,4,5]->[2,3,4,5,1,2],在第一位和第二位断开),我们称为旋转数组。给定一个值,判断这个值是否存在于这个旋转数组中。
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
bool Search(vector<int>& nums, int target) {
int start = 0, end = nums.size() - 1;
while (start <= end) {
int mid = (start + end) / 2;
if (nums[mid] == target) {
return true;
}
if (nums[mid] == nums[start]) {
start++;
}
else if (nums[mid] <= nums[end]) {
if (target > nums[mid] && target <= nums[end]) {
start = mid + 1;
}
else {
end = mid - 1;
}
} else {
if (target >= nums[start] && target < nums[mid]) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
return false;
}
}
void main() {
vector<int> input = { 2,5,6,0,0,1,2 };
int target = 0;
cout << "find the value or not : " <<Search(input,target)<< endl;
}