更新二分搜索 tips

This commit is contained in:
YDZ
2019-09-22 18:42:44 +08:00
parent 13113324b4
commit 7887ac0e17

123
README.md
View File

@@ -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 + 1high = 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)||