二分搜索是一个效率很高的算法。一个良好实现的二分搜索算法,其时间复杂度可以达到Θ(log??)
,而空间复杂度只有??(1)
。
要注意二分搜索的适用场景:
func binarySearch(a []int, t int) int{
l,r := 0,len(a)-1
for l<=r {
mid := l + (r-l)>>1
if a[mid] == t {
return mid
} else if a[mid] < t {
l = mid+1
} else {
r = mid-1
}
}
return -1
}
func sqrt(x float64, p float64) float64 {
l, r := 0.0, x
for {
mid := l + (r-l)/2.0
t := mid * mid
if math.Abs(x-t) < p {
return mid
} else if t > x {
r = mid
} else {
l = mid
}
}
}
func binarySearchFirst(a []int, t int) int{
l,r := 0,len(a)-1
for l<r {
mid := l + (r-l)>>1
if a[mid] < t {
l = mid+1
} else {
r = mid
}
}
if a[l] == t {
return l
}
return -1
}
func binarySearchLast(a []int, t int) int{
l,r := 0,len(a)-1
for l<r {
mid := l + (r-l)>>1
if a[mid] <= t {
l = mid
} else {
r = mid - 1
}
}
if a[l] == t {
return l
}
return -1
}
func binarySearch(a []int, t int) int{
l,r := 0,len(a)-1
for l<=r {
mid := l + (r-l)>>1
if a[mid] < t {
l = mid + 1
} else {
r = mid - 1
}
}
if l < len(a) {
return l
}
return -1
}
func binarySearch(a []int, t int) int{
l,r := 0,len(a)-1
for l<=r {
mid := l + (r-l)>>1
if a[mid] <= t {
l = mid + 1
} else {
r = mid - 1
}
}
if l < len(a) {
return l
}
return -1
}
给定升序数组,从任意位置切一刀后左右互换后构成新的数组,在该数组中查找目标值t的下标
分析的核心事如何确定有序数段
func splitSearch(arr []int, t int, i int, j int) int {
for i <= j {
//获取中间值
mid := i + (j-i)>>1
//刚好相等,得到答案
if arr[mid] == t {
return mid
} else if arr[mid] < t {
//mid-j之间有序,则使用正常二分查找
if t <= arr[j] {
i = mid + 1
} else {
j = mid - 1
}
} else {
//i-mid之间有序,使用正常二分查找
if t >= arr[i] {
j = mid - 1
} else {
i = mid + 1
}
}
}
return -1
}
LeetCode 300. Longest Increasing Subsequence
连续最大子序列,经典的题目,主要思路两种
动态规划
dp[i]
表示0到i的数组中,已i为结尾的最大子序列长度,则递归方程为dp[i+1]=max(dp[j]+1),0<=j<=i
二分查找+栈
设定一个数组栈,遍历数组,每次通过二分查找寻找p[i]
在数组栈中最小适合位置,如果有则替换,没有则把p[i]
追加,最后答案为数组栈的大小
func lengthOfLIS(nums []int) int {
ret := make([]int,0,len(nums))
for i:=0;i<len(nums);i++{
t := find(ret,nums[i])
if t == -1 {
ret = append(ret,nums[i])
} else {
ret[t] = nums[i]
}
}
return len(ret)
}
//找到第一个大于或等于k的位置
func find(nums []int, k int) int {
ll := len(nums) -1
if ll < 0 {
return -1
}
l, r := 0, ll
for l < r {
mid := l + (r-l)>>1
if nums[mid] == k {
return mid
} else if nums[mid] > k {
r = mid
} else {
l = mid + 1
}
}
if l == ll && nums[l] < k {
return -1
}
return l
}
原文:https://www.cnblogs.com/weiweng/p/12485874.html