首先看leetcode33.搜索旋转排序数组。它是要在某数组中找到“具体的某个值”,那么模板为:
while(left<=right){
int mid = left+(right-left)/2;
if(nums[mid]==target) return mid;
if(nums[mid]<target) left = mid+1;
else right = mid-1;
}
这里之所以要用left<=right,是因为到最后left+1==right的时候,有可能right是那个符合条件的值,但是mid为left(向下取整)。如果这时候就return了,相当于错过了right这个“正确值”。
再看leetcode153. 寻找旋转排序数组中的最小值。这种题求的不是具体的target,而是“第一个符合某条件的值”。比如这题,求的就是“第一个小于nums[len-1]的值”。这种题的模板为:
while(left<right){
int mid = left+(right-left)/2;
if(nums[mid]<target) right = mid;
else left = mid+1;
}
return left;
之所以用的是(left<right),是因为到最后输出的时候肯定存在(left==right),代表这个“逼近值”已经被求出来了。这里有个点需要注意的是:这种模板只适用于求“从左往右找,第一个符合条件的值”。因为这样的话,每次mid一定不等于left,不会造成死循环
如果不得不”从右往左找”,那mid就需要向上取整了,比如leetcode69. x 的平方根。模板为:
while(left<right){
int mid = left+(right-left+1)/2;
if(nums[mid]>target) right = mid-1;
else left = mid;
}
return left;
这三道题的代码分别为:
leetcode33.搜索旋转排序数组
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int left = 0;
int right = len-1;
while(left<=right){
int mid = left+(right-left)/2;
if(nums[mid]==target) return mid;
if(nums[left]==target) return left;
if(nums[right]==target) return right;
if(nums[mid]<nums[left]){
if(target>nums[mid]&&target<nums[right]){
left = mid+1;
}else{
right = mid-1;
}
}else{
if(target>nums[left]&&target<nums[mid]){
right = mid-1;
}else{
left = mid+1;
}
}
}
return -1;
}
}
leetcode153. 寻找旋转排序数组中的最小值
class Solution {
public int findMin(int[] nums) {
int len = nums.length;
int left = 0;
int right = len-1;
while(left<right){
int mid = left+(right-left)/2;
if(nums[mid]<nums[right]) right = mid;
else left = mid+1;
}
return nums[left];
}
}
leetcode69. x 的平方根
class Solution {
public int mySqrt(int x) {
if(x==0||x==1) return x;
int left = 0;
int right = x/2;
while(left<right){
int mid = left+(right-left+1)/2;
if(mid<=x/mid) left = mid;
else right = mid-1;
}
return left;
}
}