mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2026-03-13 10:02:05 +08:00
更新二分搜索 tips
This commit is contained in:
123
README.md
123
README.md
@@ -1800,6 +1800,129 @@ func updateMatrix_BFS(matrix [][]int) [][]int {
|
||||
|
||||
## Binary Search
|
||||
|
||||
![]()
|
||||
|
||||
- 二分搜索的经典写法。需要注意的三点:
|
||||
1. 循环退出条件,注意是 low <= high,而不是 low < high。
|
||||
2. mid 的取值,mid := low + (high-low)>>1
|
||||
3. low 和 high 的更新。low = mid + 1,high = mid - 1。
|
||||
|
||||
```go
|
||||
func binarySearchMatrix(nums []int, target int) int {
|
||||
low, high := 0, len(nums)-1
|
||||
for low <= high {
|
||||
mid := low + (high-low)>>1
|
||||
if nums[mid] == target {
|
||||
return mid
|
||||
} else if nums[mid] > target {
|
||||
high = mid - 1
|
||||
} else {
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
```
|
||||
|
||||
- 二分搜索的变种写法。有 4 个基本变种:
|
||||
1. 查找第一个与 target 相等的元素,时间复杂度 O(logn)
|
||||
2. 查找最后一个与 target 相等的元素,时间复杂度 O(logn)
|
||||
3. 查找第一个大于等于 target 的元素,时间复杂度 O(logn)
|
||||
4. 查找最后一个小于等于 target 的元素,时间复杂度 O(logn)
|
||||
|
||||
```go
|
||||
// 二分查找第一个与 target 相等的元素,时间复杂度 O(logn)
|
||||
func searchFirstEqualElement(nums []int, target int) int {
|
||||
low, high := 0, len(nums)-1
|
||||
for low <= high {
|
||||
mid := low + ((high - low) >> 1)
|
||||
if nums[mid] > target {
|
||||
high = mid - 1
|
||||
} else if nums[mid] < target {
|
||||
low = mid + 1
|
||||
} else {
|
||||
if (mid == 0) || (nums[mid-1] != target) { // 找到第一个与 target 相等的元素
|
||||
return mid
|
||||
}
|
||||
high = mid - 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// 二分查找最后一个与 target 相等的元素,时间复杂度 O(logn)
|
||||
func searchLastEqualElement(nums []int, target int) int {
|
||||
low, high := 0, len(nums)-1
|
||||
for low <= high {
|
||||
mid := low + ((high - low) >> 1)
|
||||
if nums[mid] > target {
|
||||
high = mid - 1
|
||||
} else if nums[mid] < target {
|
||||
low = mid + 1
|
||||
} else {
|
||||
if (mid == len(nums)-1) || (nums[mid+1] != target) { // 找到最后一个与 target 相等的元素
|
||||
return mid
|
||||
}
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// 二分查找第一个大于等于 target 的元素,时间复杂度 O(logn)
|
||||
func searchFirstGreaterElement(nums []int, target int) int {
|
||||
low, high := 0, len(nums)-1
|
||||
for low <= high {
|
||||
mid := low + ((high - low) >> 1)
|
||||
if nums[mid] >= target {
|
||||
if (mid == 0) || (nums[mid-1] < target) { // 找到第一个大于等于 target 的元素
|
||||
return mid
|
||||
}
|
||||
high = mid - 1
|
||||
} else {
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// 二分查找最后一个小于等于 target 的元素,时间复杂度 O(logn)
|
||||
func searchLastLessElement(nums []int, target int) int {
|
||||
low, high := 0, len(nums)-1
|
||||
for low <= high {
|
||||
mid := low + ((high - low) >> 1)
|
||||
if nums[mid] <= target {
|
||||
if (mid == len(nums)-1) || (nums[mid+1] > target) { // 找到最后一个小于等于 target 的元素
|
||||
return mid
|
||||
}
|
||||
low = mid + 1
|
||||
} else {
|
||||
high = mid - 1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
```
|
||||
|
||||
- 在基本有序的数组中用二分搜索。经典解法可以解,变种写法也可以写,常见的题型,在山峰数组中找山峰,在旋转有序数组中找分界点。第 33 题,第 81 题,第 153 题,第 154 题,第 162 题,第 852 题
|
||||
|
||||
```go
|
||||
func peakIndexInMountainArray(A []int) int {
|
||||
low, high := 0, len(A)-1
|
||||
for low < high {
|
||||
mid := low + (high-low)>>1
|
||||
// 如果 mid 较大,则左侧存在峰值,high = m,如果 mid + 1 较大,则右侧存在峰值,low = mid + 1
|
||||
if A[mid] > A[mid+1] {
|
||||
high = mid
|
||||
} else {
|
||||
low = mid + 1
|
||||
}
|
||||
}
|
||||
return low
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
| Title | Solution | Difficulty | Time | Space |收藏|
|
||||
| ----- | :--------: | :----------: | :----: | :-----: | :-----: |
|
||||
|[50. Pow(x, n)](https://leetcode.com/problems/powx-n)| [Go](https://github.com/halfrost/LeetCode-Go/tree/master/Algorithms/0050.%20Pow(x%2C%20n))| Medium | O(log n)| O(1)||
|
||||
|
||||
Reference in New Issue
Block a user