二分法和双指针(一点点)

这几天在写论文,没有大块的时间来做项目,就一边修修改改毕设一边写论文,顺便一天刷几道算法题。(力扣上面的算法入门内容)

二分法

1.给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

我的思路:一开始看到这个第一想法就是数组的filter方法。filter函数的参数为

  • callback回调函数,函数的参数
    • element:数组中当前正在处理的元素。
    • index可选:正在处理的元素在数组中的索引。
    • array可选:调用了filter 的数组本身。
  • thisArg可选:执行 callback 时,用于 this 的值。
    所以我希望使用通过回调函数种element和index两个参数得到符合的元素的下标。但是一直是undefined,我也没看出来哪里有错(应该是真的有错,因为不符合应该会报“超出时间限制”或者其他的错误提示),后面想起题目是二分法,又重新理了一下思路:

先找到中间值(类似于数学中的中位数,因为这个数组给了条件是升序的),就把数组分成了左右两部分,与中间值对比,判断target目标值在哪个部分,把所在部分继续二分查找,就是这样的思路,直到边界值不符合min<=max,跳出while,没找到就返回-1。答题思路是没错,但是实现起来不够严谨吧,学到了几个优化的地方:

优化

  1. 中间值mid的计算:
    我用的是mid=(min+max)/2;但是官方给出的是mid=min+(max-min)/2,这样可以防止数组越界的问题(虽然我觉得发生的可能性比较微乎其微,但是考虑全面肯定是更好的)。还有我们用JS写的话需要向下取整,写成:Math.floor((min+max)/2)
  2. mid的取值:
    我直接令max或者min=mid 了,但是思考了答案,觉得确实没错。他给的是max= mid-1或min=mid+1;因为这个数组查找的是一个闭区间,也就是说,不符合的那部分,边界值我们是比较过的,舍弃之后,把符合的对应范围缩小1,就是把边界值移动一位,其实这个边界值我们后面还是一样会比较的,但是没有必要再去比较开始比过的那个边界。所以确实这种写法更好。

2.你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version
是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

分析:
这道题也是一道二分法的题,但是与上面不同的是,这个找的是分界的点。即A版本为false,相邻的B版本为true,应找到B并返回

解题思路

  1. 与上面一样,还是需要mid=min+(max-min)/2来防止溢出。符合循环的条件为left<right。这道题需要判断两个版本,即前面为false,后面为true,当二者相等的时候就说明找到了那个点,就可以跳出循环
  2. 不一样的是,当发现mid为true的时候,应该让右区间的截止值等于mid,即right=mid。因为可能mid-1的值就是false,而mid为true,所以mid就是我们要寻找的版本。而mid为false,则左区间值应该为mid+1,说明为true的版本一定在这版本之后。也就是说,确定与答案无关的边界值应该省略过去,但是不确定的,可能还需要比较的,就不能往内推1

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
例如:输入: nums = [1,3,5,6], target = 5
输出: 2

分析
这道题就是一个找值加比大小的题。因为题中的nums是一个无重复元素的升序数组,这种情况一般都应该想到可以用二分法。这道题还是要弄清楚上面的两个条件:一个是

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值