算法细节问题分析
愚者千虑,必有一得
二分查找
https://blog.csdn.net/xushiyu1996818/article/details/102482609
左右开闭问题
值的查找
最简单最直观的方式,这种情况下,如果值不存在在数组中,l,r 会逐渐收靠到数组的边界,直到跳出范围
func binSearch0(nums []int, target int) (index int) {
l, r := 0, len(nums)-1
for l <= r {
//搜索区间为[0,len(nums)-1]
m := l + (r-l)/2
if nums[m] == target {
return m
} else if nums[m] < target {
l = m + 1
} else {
r = m - 1
}
}
return -1
}
存在循环的情况
上面这种情况,稍微修改就会产生几种常见的会产生循环的情况
a. l,r 赋值时,没有将m剔除下一次查找范围
func binSearch0(nums []int, target int) (index int) {
l, r := 0, len(nums)-1
for l <= r {
m := l + (r-l)/2
if nums[m] == target {
return m
} else if nums[m] < target {
l = m
} else {
r = m
}
}
return -1
}
这种情况下通常会产生循环的情况 r-l =1
m = l + (r-l)/2 => m =l;然后恰好,nums[m]< target;l = m=> l = l;
搜索范围
当 l < r 而不是 l<=r 时,二分查找的范围实际上是两边开区间(0,l),放弃了查询l==r的情况,这种情况可以通过打补丁实现
func binSearch0(nums []int, target int) (index int) {
l, r := 0, len(nums)-1
for l < r {
//搜索区间为[0,len(nums)-1]
m := l + (r-l)/2
if nums[m] == target {
return m
} else if nums[m] < target {
l = m + 1
} else {
r = m - 1
}
}
return nums[l]==target?l:-1
}
边界查找问题
边界查找的实质就是,寻找某个target第一次和最后一次出现的index
寻找左边界
func leftBound(nums []int, target int) (index int) {
l, r := 0, len(nums)
for l < r {
m := l + (r-l)/2
if nums[m] == target {
r = m
} else if nums[m] < target {
l = m + 1
} else {
r = m
}
}
return l
}
寻找右边界
func leftBound(nums []int, target int) (index int) {
l, r := 0, len(nums)
for l < r {
m := l + (r-l)/2
if nums[m] == target {
l = m + 1
} else if nums[m] < target {
l = m + 1
} else {
r = m
}
}
return l-1
}
# 快排
![](https://img2020.cnblogs.com/blog/895672/202108/895672-20210811144136935-2145787125.png)
1. 左边界和右边界谁在前决定了最终停在哪个元素上,因为枢轴默认取得第一个元素,因此最好和停在小于arr[p]的首个元素交换,因此最好和r交换
2. l<r 可能会导致停在同一个指针上最后再交换一次导致排序错误
# 插入排序
I'm a fucKing fake coder!