6 - 二分查找(1)
最近总是想看一些治愈的东西才能有力量去做事。当下应该是生命中最重要的阶段之一,一定要加油啊, 坚持下去!
35. 搜索插入位置
题目大意:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。
解题思路:使用二分查找找到该元素的位置或者第一个小于该元素的位置,若没有则插入到末尾。其中,需要注意一些细节的实现。
代码:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int low = 0,high = n-1;
while(low <= high){
int mid = low + (high - low)/2;
if(nums[mid] >= target){
high = mid - 1;
}
else {
if((mid == n - 1)||(nums[mid+1] >= target)){//不能交换位置否则会导致数组越界
return mid+1;
}
low = mid + 1;
}
}
return 0;//第一个位置
}
69. x 的平方根
题目大意:给你一个非负整数x,计算并返回 x 的 算术平方根。由于返回类型是整数,结果只保留 整数部分,小数部分将被舍去。
解题思路:仍然是二分查找,从0开始至x,注意判断目标值的平方小于x,但目标值的平方加一大于x,这种情况符合答案要求。
代码:
int mySqrt(int x) {
long low = 0, high = x;
while(low <= high){
long mid = low + (high - low)/2;
if(mid * mid > x){
high = mid - 1;
}
else if((mid * mid < x)&&(mid + 1)*(mid + 1) > x){
return mid;
}
else if(mid * mid == x)
return mid;
else
low = mid + 1;
}
return 0;
}
278. 第一个错误的版本
题目大意:你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
解题思路:通过二分查找查找到第一个版本号是错误的,当一个版本是错误的且它的前一次版本是正确的,则它是第一个错误的版本。
代码:
int firstBadVersion(int n) {
int low = 0, high = n;
while(low <= high){
int mid = low + (high - low)/2;
if(isBadVersion(mid) && !isBadVersion(mid-1))
return mid;
else if(!isBadVersion(mid))
low = mid + 1;
else
high = mid -1;
}
return 0;
}
367. 有效的完全平方数
题目大意:给定一个 正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 true,否则返回 false。
解题思路:该题同样用二分查找一个数来判断是否其平方为所给数。注意,需要进行强制类型转换,否则数字会int越界。
代码:
bool isPerfectSquare(int num) {
long low = 0, high = num/2+1;
while(low <= high){
int mid = low + (high - low)/2;
long s = (long)mid * mid;
if( s > num)
high = mid - 1;
else if( s < num){
low = mid + 1;
}
else if(s == num)
return true;
}
return false;
}
374. 猜数字大小
题目大意:题目选出1-n中随机一个数字,猜测一个数字,给定函数可以判定该数字和选出的数字大小,进行判定,求找出题目选出的数字。
解题思路:使用二分查找,与上述所有题思路基本相同,没有特殊的点。
代码:
int guessNumber(int n) {
int low = 0, high = n;
while(low <= high){
int mid = low + (high - low)/2;
if(guess(mid) == 0)
return mid;
else if(guess(mid) == 1)
low = mid + 1;
else
high = mid -1;
}
return 0;
}