二分查找的前提:数据有序
二分查找的条件分支:
- nums[mid]==target
- nums[mid]<target
- nums[mid]>target
二分查找的搜索区间表示形式:
-
左闭右开
区间为空的条件是left==right
-
左闭右闭
区间为空的条件是left>right
二分查找结束的条件:查找区间为空,或者找到元素
二分查找有的时候我会写出死循环来,仔细思考了一下,必须每次收缩边界的时候,都排除掉mid。
习题:
习题解答:
第二题和第一题不同的地方在于结束条件,第二题的结束条件只能是查找区间为空,找到元素后还要继续进行查找。
第二题查找结束后,还必须对查找的最后一个元素进行判断,如果等于target就返回index,不等于就返回-1。由于有三个分支,我们只需要考虑最后的元素进入nums[mid]==target分支的情况,其余的分支必定不相等。那么我们假设它进了这个分支,并对这个最后位置的元素再重新判断一次,如果相等就找到了,如果不相等就没找到。
第一题答案:
左闭右闭搜索区间的写法:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
let left = 0;
let right = nums.length-1;
while(left<=right){
const mid = left + Math.floor((right-left)/2);
if(nums[mid]==target){
return mid;
}else if(nums[mid]>target){
right = mid-1;
}else if(nums[mid]<target){
left = mid+1;
}
}
return -1;
};
左闭右开搜索区间的写法:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var search = function(nums, target) {
let left = 0;
let right = nums.length;
while(left<right){
const mid = left + Math.floor((right-left)/2);
if(nums[mid]==target){
return mid;
}else if(nums[mid]>target){
right = mid;
}else if(nums[mid]<target){
left = mid+1;
}
}
return -1;
};
第二题答案:
左闭右开搜索区间的写法:
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var searchRange = function(nums, target) {
return [findLeft(nums, target), findRight(nums, target)]
};
var findLeft = function(nums, target){
let left = 0;
let right = nums.length;
while(left<right){
let mid = left + Math.floor((right-left)/2);
if(nums[mid]==target){
right = mid;
}else if(nums[mid]<target){
left = mid+1;
}else if(nums[mid]>target){
right = mid;
}
}
if(nums[left]==target){
return left
}
return -1;
}
var findRight = function(nums, target){
let left = 0;
let right = nums.length;
while(left<right){
let mid = left + Math.floor((right-left)/2);
console.log(left, mid, right)
if(nums[mid]==target){
left = mid+1;
}else if(nums[mid]<target){
left = mid+1;
}else if(nums[mid]>target){
right = mid;
}
}
if(nums[right-1]==target){
return right-1;
}
return -1;
}
左闭右闭搜索区间的写法:
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var searchRange = function(nums, target) {
return [fundLeft(nums, target), fundRight(nums, target)]
};
var fundLeft = function(nums, target){
let left = 0;
let right = nums.length - 1;
while(left<=right){
let mid = left + Math.floor((right-left)/2);
if(nums[mid]==target){
right = mid-1;
}else if(nums[mid]<target){
left = mid+1;
}else if(nums[mid]>target){
right = mid-1;
}
}
if(nums[left]==target){
return left;
}
return -1;
}
var fundRight = function(nums, target){
let left = 0;
let right = nums.length - 1;
while(left<=right){
let mid = left + Math.floor((right-left)/2);
if(nums[mid]==target){
left = mid+1;
}else if(nums[mid]<target){
left = mid+1;
}else if(nums[mid]>target){
right = mid-1;
}
}
if(nums[right]==target){
return right;
}
return -1;
}