算法通关村——二分查找的应用

​​​​​​852. 山脉数组的峰顶索引 - 力扣(LeetCode)

为什么- left初始化为1,表示左边界
- right初始化为n-2,表示右边界?

1. left 初始化为 1
因为这是一个寻找山峰的题目,数组呈现山形,左右两边一定小于中间的峰值。
所以可以初始化 left 为 1,排除 arr[0] 作为候选解,这样可以缩小查找范围。
2. right 初始化为 n-2
因为山峰不可能出现在数组最右边(不然右边就更大了),所以可以排除 arr[n-1]。
初始化 right 为 n-2 就是为了跳过这个不可能的候选。
3. 初始化的作用
这样初始化左右边界,就可以排除山峰不可能出现的两个位置,缩小了二分查找的范围,优化了时间复杂度。
4. 保证左闭右闭
left=1 和 right=n-2 也可以确保左闭右闭的区间,方便处理边界条件。
5. 和Mid计算吻合
在计算 mid 时,mid = (left + right) / 2,与 1 和 n-2 的边界初始化是吻合的。
综上,这种左右边界的初始化方式,既保证了区间的左闭右闭,也缩小了查找范围,排除了不可能的候选,优化了算法的效率。 

上述代码中  arr.size是从0开始,还是从1开始?

在C++中,std::vector的size()方法返回的是向量中元素的数量,索引是从0开始的。
所以在这个代码中:
int n = arr.size();
表示的就是向量arr中元素的总个数,而不是最大索引。
举个例子,如果arr中有5个元素,那么:
- arr.size() 返回的值是5 
- 元素索引范围是0~4
所以在这个代码中,n表示的是数组arr的元素总数,而不是最大索引。
数组索引arr[i]仍然是从0开始,最大索引为n-1。

为什么当 left + right = 7 时,mid 不是 4 而是 3 呢?

主要原因是在计算 mid 时使用的是整除 /,而不是普通的除法:mid = (left + right) / 2这里的 / 是整除运算符,会自动向下取整。所以当 left + right = 7 时:(left + right) / 2
= 7 / 2
= 3 (向下取整)如果是普通的除法,结果就会是 3.5,接近 4。但因为这里是整除,所以计算结果直接取整得到 3。而不是舍入后的 4。这也更符合二分查找中 midpoint 的计算方式,将中间索引看作是左右边界的中点。这种向下取整的计算方式,可以将数组对半分成两个区间,使得二分查找更加清晰。所以这里 mid 的计算采用的是整除,当 left + right = 7 时,mid 的结果是 3,而不是 4。这种向下取整的计算方式在二分查找中很常见,可以更清晰地对半分割数组区间。

用这个例子能很好的去理解整个流程。

二分
往常我们使用「二分」进行查值,需要确保序列本身满足「二段性」:当选定一个端点(基准值)后,结合「一段满足 & 另一段不满足」的特性来实现“折半”的查找效果。

但本题求的是峰顶索引值,如果我们选定数组头部或者尾部元素,其实无法根据大小关系“直接”将数组分成两段。

但可以利用题目发现如下性质:由于 arr 数值各不相同,因此峰顶元素左侧必然满足严格单调递增,峰顶元素右侧必然不满足。

因此 以峰顶元素为分割点的 arr 数组,根据与 前一元素/后一元素 的大小关系,具有二段性:

峰顶元素左侧满足 arr[i−1]<arr[i]arr[i-1] < arr[i]arr[i−1]<arr[i] 性质,右侧不满足
峰顶元素右侧满足 arr[i]>arr[i+1]arr[i] > arr[i+1]arr[i]>arr[i+1] 性质,左侧不满足
因此我们可以选择任意条件,写出若干「二分」版本。

作者:宫水三叶
链接:https://leetcode.cn/problems/peak-index-in-a-mountain-array/solutions/828434/gong-shui-san-xie-er-fen-san-fen-cha-zhi-5gfv/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

或者还有一种理解思路   就是如果你在上升阶段  我就把你左半部分砍掉  以此类推

当你刚好在顶峰的时候  就退出循环。

153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode)

为什么high = pivot;?而low = pivot + 1?(可以自己思考一下)

猜想:在上面的话  一定不是我想要的  所以可以pass掉

这道题其实和上面一个题目很像。

剑指 Offer 53 - II. 0~n-1中缺失的数字 - 力扣(LeetCode)

中序与搜索树原理

700. 二叉搜索树中的搜索 - 力扣(LeetCode)

嘶。。。。。。  这个和二分查找有什么关系吗?没懂

98. 验证二叉搜索树 - 力扣(LeetCode)

long long

为什么这个 long long maxVal = LONG_MIN; // 因为后台测试数据中有int最小值放在这个地方会报错?

这个错误可能是因为在递归调用时,每次都会重新定义一个新的maxVal变量,而不是在整个递归过程中共享同一个变量。因此,当递归返回到上一层时,maxVal的值会被重置为LONG_MIN,而不是之前的最大值。为了解决这个问题,可以将maxVal定义为类的成员变量,这样在整个递归过程中都可以共享同一个变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值