1. 二分查找框架
int binarySearch ( int [ ] nums, int target) {
int left = 0 ;
int right = . . .
while ( . . . ) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] == target) {
. . .
} else if ( nums[ mid] < target) {
left = . . .
} else if ( nums[ mid] > target] ) {
right = . . .
}
}
return . . .
}
⼆分查找小技巧 不要出现 else,⽽是把所有情况⽤ else if 写清 楚,这样可以清楚地展现所有细节。
2. 基本的二分查找(寻找一个数)
搜索区间:[left, right] 左闭右闭
当 nums[mid] 被检测后,分割成两个区间:[left, mid-1] 和 [mid+1, right] while 终止条件:left == right + 1
int binarySearch ( int [ ] nums, int target) {
int left = 0 ;
int right = nums. length - 1 ;
while ( left <= right) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] == target) {
return mid;
} else if ( nums[ mid] < target) {
left = mid + 1 ;
} else if ( nums[ mid] > target] )
right = mid - 1 ;
}
return - 1 ;
}
3. 寻找左侧边界的二分查找
搜索区间:[left, right) 左闭右开
当 nums[mid] 被检测后,分割成两个区间:[left, mid) 和 [mid+1, right) while 终止条件:left == right
int leftBound ( int [ ] nums, int target) {
if ( nums. length == 0 ) {
return - 1 ;
}
int left = 0 ;
int right = nums. length;
while ( left < right) {
int mid = left + ( 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 ( left == nums. length) {
return - 1 ;
}
return nums[ left] == target ? left : - 1 ;
}
搜索区间:[left, right] 左闭右闭
当 nums[mid] 被检测后,分割成两个区间:[left, mid-1] 和 [mid+1, right] while 终止条件:left == right + 1
int leftBound ( int [ ] nums, int target) {
int left = 0 ;
int right = nums. length - 1 ;
while ( left <= right) {
int mid = left + ( 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 ( left >= nums. length || nums[ left] != target) {
return - 1 ;
}
return left;
}
4. 寻找右侧边界的二分查找
搜索区间:[left, right) 左闭右开
当 nums[mid] 被检测后,分割成两个区间:[left, mid) 和 [mid+1, right) while 终止条件:left == right
int rightBound ( int [ ] nums, int target) {
if ( nums. length == 0 ) {
return - 1 ;
}
int left = 0 ;
int right = nums. length;
while ( left < right) {
int mid = left + ( 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;
}
if ( right == 0 ) {
return - 1 ;
}
return nums[ right- 1 ] == target ? ( right- 1 ) : - 1 ;
}
搜索区间:[left, right] 左闭右闭
当 nums[mid] 被检测后,分割成两个区间:[left, mid-1] 和 [mid+1, right] while 终止条件:left == right + 1
int rightBound ( int [ ] nums, int target) {
int left = 0 ;
int right = nums. length - 1 ;
while ( left <= right) {
int mid = left + ( 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 ( right < 0 || nums[ right] != target) {
return - 1 ;
}
return right;
}