代码随想录训练营第一天 | 二分查找 + 快慢指针

先注声明:解题思路:借鉴、归纳及总结     意在记录学习过程(非原创)

                  但文字部分及所用图片均来自个人        谢绝转载


1.二分法

 标签:不甘心用暴力算法缓慢遍历,企图通过二分不断缩小搜索区间,以降低时间复杂度

  使用前提:一般为有序数组

  时间复杂度:O(logn)

基础款LeetCode 704   704. 二分查找 - 力扣(Leetcode)

        tip: 二分法确实有许多写法,了解思路后,熟悉一种写法即可

变种1:返回插入位置 LeetCode 35     35. 搜索插入位置 - 力扣(Leetcode)

小结:仔细对比,会发现和基础款几乎没有区别。

           唯一修改的地方就是,未找到的return值由-1 改成了 left。

           这其实很好理解,因为二分法最终情况,左右指针一定会逼近。

变种2:查找上下界  LeetCode 34     34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(Leetcode)

 小结:首先这种题也存在很多解法,这里仅记叙我最习惯思考的一种(不一定最简便)。

            以卡下界为例,本质是查找第一个与之相等的元素。

            与基础款作对比,修改的代码看上去仅仅是return middle 的 if 条件。

            首先,与目标值相等必是返回的条件之一。但如何是保证出现的第一个?

            利用数组的有序性就可以——第一个相等元素的左端值一定比目标值target 小,

            即需满足nums[middle-1] < target

            *但这里需要仍需注意middle-1的合法性。(这很重要)

            *存在特殊情况nums[middle-1]不合法,即middle == 0。此时元素一定满足返回条件。

            因此,判断条件为 if(nums[middle]==target && (middle == 0||nums[middle-1] < target))。

            *还需要注意的一点是:倘若交换 || 前后顺序,写成:

            if(nums[middle]==target && (nums[middle-1] < target || middle == 0))也是不正确的。

            因为机器执行是从左往右判断,所以仍会出现数组访问越界的情况。

            所以必须middle==0 写在前,nums[middle-1] < target 写在后。

            这里有一个不经意的小心机。注意看else。

            不同于基础款的二分法,这里由于if 扩充了条件,else 包含的条件会变多。

            但因为我们的目标是搜索下界,所以会有一个往左搜索的趋势

             所以else 的情况下,修改的一定是right的边界。(这点记好)

        

             现在回过头来看卡上界,与下界是一个道理。

             首先是if 条件扩充:middle 走到右侧尽头或者middle 右侧的数比target大。

             其次是注意else 下,修改的是left的边界。

变种3:查找第一个/最后一个 大于/小于目标值的元素下标

说明:实际上这种情况和变种2相差不太多。

          查找第一个就相当于查下界。查最后一个相当于查上界。

          变种2查找相等情况,变种3查找大于/小于也仅仅是修改判断条件。

现已,查找第一个大于目标值为例:

 小结:注意几个事项即可(以下讨论基于“第一个大于”的题干)

            1.修改 if  条件,确保middle位置的数满足大于目标值的条件

                同时确保左侧的数若存在,则必小于等于目标值target。

            2.修改之后的else if 及else.但要确保最后else 下修改的是right,已达到往左逼近的目的。

其它变种情况类似,此处不再赘述。


2.快慢指针

    定性描述:快慢指针是双指针法中的一种,可用于解决(链表上)环的问题。

    名词解释:使用速度不同的指针用于链表、数组等    快指针:fast    满指针:slow

经典题型:LeetCode 27 移除元素   27. 移除元素 - 力扣(Leetcode)

    思路:用两层for循环暴力求解可以,但是时间复杂度过高,为O(n²)。

              不如用双指针原地修改数组,可使时间复杂度降为O(n)。

小结: 核心想法就是,以 fast 获取“新数组”的“新元素”,赋值在slow的数组之上。

            实质是对两个“相同的数组”进行操作。

   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值