双指针问题的算法

双指针主要分两类: 快慢指针和左右指针

对于 链表问题, 我们一般可以使用 快慢指针解决
所谓的快慢指针是指, 使用两个指针按照不同的速度前进, 有两个指针我们可以确定:

一些题目

注意: 两个指针相遇则有环 (类比在操场跑步, 速度不相等总能相遇)

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        if not head:
            return False
        fast_node = head.next
        slow_node = head
        while fast_node and fast_node.next:
            if slow_node == fast_node:
                return True
            fast_node = fast_node.next.next
            slow_node = slow_node.next
        return False

又比如:

左右指针一般的形式就是我们常说的 二分查找(二分搜索)

一般的使用方式:

def binary_search(nums: List[int], target: int):
    left = 0
    right = ...

    while ...:
        mid = left + (right - left) / 2
        if nums[mid] == target:
            ...

        elif nums[mid] < target:
            left = ...

        elif nums[mid] > target:
            right = ...

    return ...

我们需要的注意点为 ...部分:

对于一些问题, 我们可以将问题的区间统一为 [left : right], 即 right = len(nums) - 1while left <= right< code><!--=-->

比如:
返回某个值的问题

def binary_search(nums: List[int], target: int):
    left = 0
    right = len(nums) - 1
    while left  target:
            right = mid - 1
        elif nums[mid] == target:
            # 直接返回
            return mid
    return -1

返回左边界的问题

def left_bound(nums: List[int], target: int):
    left = 0
    right = len(nums) - 1
    while left  target:
            right = mid - 1
        elif nums[mid] == target:
            # 别返回,锁定左侧边界
            right = mid - 1

    # 最后要检查 left 越界的情况
    # left可能超出范围 即 >= len(nums)
    if left >= len(nums) or nums[left] != target:
        return -1
    return left

结束条件为: [right + 1 : right](如: [3 : 2])
返回左边界 left

返回右边界的问题

def right_bound(nums: List[int], target: int):
    left = 0
    right = len(nums) - 1
    while left  target:
            right = mid - 1
        elif nums[mid] == target:
            # 别返回,锁定右侧边界
            left = mid + 1

    # 最后要检查 right 越界的情况
    if right < 0 or nums[right] != target:
        return -1

    return right

结束条件为: [right + 1 : right](如: [3 : 2])
返回右边界 right

在leetcode上对应的题目:

滑动窗口是双指针的一种, 也可以说是左右指针的一种
其主要解决的是 子串问题
所谓的子串问题是指: 一个长的字符串是否全部包含 一个短的字符串 (包括数量)
滑动窗口的思想:
① 我们可以设两个指针, 分别对应窗口的左右边界
② 右边界向右扩大窗口, 直到找到符合条件的子串
③ 左边界向右缩小窗口, 更新数据, 根据题目是否返回
④ 假如还未返回, 则重复②和③
⑤ 根据题目是否返回

模板:

def sliding_window(s: str, t: str):
"""
    :param s 大的字符串
    :param t 小的字符串
    :return 根据题目返回

"""
    need = {}  # 存放需要的字符数
    windows = {}  # 存放当前窗口中的字符数
    # 记录需要的字符数
    for char in t:
        # 需要字符的数量自增1
        need[char] = need.setdefault(char, 0) + 1  # setdefault作用字典中不存在字符时, 返回0
    # 左右边界的指针
    left = right = 0
    # 用于记录已经通过检验的字符数
    valid = 0
"""
    假如有其他变量可以在这里添加
"""
    while right < len(s):
        # right_char为将要移入的窗口字符
        right_char = s[right]
        # 右移窗口
        right += 1
        # 假如当前 右边界 的字符,为需要的字符
        if right_char in need:
"""
            更新数据
            一般是
            1. 当前窗口的数据
            2. 通过的 字符数
"""
            # 记录当前窗口符合要求的字符数量
            windows[right_char] = windows.setdefault(right_char, 0) + 1
            # 假如当前字符已经符合要求
            # 通过检验的字符数 + 1
            if windows[right_char] == need[right_char]:
                valid += 1

        # 判断左边界是否可以收缩
        # !!!! 这个条件根据题目而变
        while condition:
"""
            根据题目是否在这里返回
"""

            # left_char为将要移出的窗口字符
            left_char = s[left]
            left += 1
            if left_char in need:
""""
                更新数据
                一般是
                1. 当前窗口的数据
                2. 通过的 字符数

                自定义的其他变量也在这里更新
"""
                # 假如当前字符已经符合要求
                # 通过检验的字符数 - 1
                if windows[left_char] == need[left_char]:
                    valid -= 1
                # 记录当前窗口符合要求的字符数量 - 1
                windows[left_char] = windows.setdefault(left_char, 0) - 1
"""
    根据题目是否在这里返回
"""

这个模板的主要注意点是

一些题目

Original: https://www.cnblogs.com/lczmx/p/15859259.html
Author: 403·Forbidden
Title: 双指针问题的算法

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/581327/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 一个Golang的REPL工具

    REPL为Read-Eval-Print Loop的简写,为一种简易的,可交互式的编程环境,使用者可以方便的调试相关代码: Read: 读取用户输入;Eval: 计算输入的数据;P…

    Java 2023年6月16日
    092
  • java基础4.19

    1.JAVA 的反射机制的原理。JAVA反射机制是在运行状态中,对于 任意一个类,都能够 知道这个类的 所有属性和方法;对于任意一个对象,都能够调 用它的任意一个方法;这种 动态获…

    Java 2023年6月5日
    087
  • web 网页nginx反向代理【检查到弱密码套件:不支持完全向前保密 】处理

    web 项目扫描出如下问题: 处理方式如下: 打开nginx配置文件nginx.conf,添加如下内容: python;gutter:true;ssl_ciphers ‘AES12…

    Java 2023年5月30日
    083
  • 初识JavaScript

    当使用js文件编写要在HTML中导入文件地址即 <script src></script> src:为相对路径,使用单独的js文件,可以实现代码的复用,使w…

    Java 2023年6月5日
    091
  • Java四类八种数据类型

    第一类:逻辑型boolean 第二类:文本型char 第三类:整数型(byte、short、int、long) char类型占2个字节short从-32768到32767int从-…

    Java 2023年5月29日
    0106
  • 缓存更新的另一种方法:双删策略

    上一篇说到缓存的更新操作是非幂等操作,会出现并发更新的问题。那用缓存删除操作实现缓存更新行不行,您可能觉得奇怪,删除了缓存如何更新,假设读业务先读取缓存,如果发现没有就回溯到读数据…

    Java 2023年6月16日
    095
  • 设计模式-day03

    5,结构型模式 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。 由于组合关…

    Java 2023年6月13日
    074
  • 工厂模式-理解Spring的Bean工厂(马士兵经典例子)

    工厂模式-理解Spring的Bean工厂 接面向对象里面 “老张开车去东北”的场景。链接名称 封装”老张开车去东北”里面的交通工具,…

    Java 2023年5月30日
    0103
  • 美团动态线程池实践思路,开源了(二)

    大家好,动态线程池项目DynamicTp开源一个多月,目前400多star,说明还是比较受欢迎的,现在已经有一些小伙伴在接入使用或者即将接入使用了,为了项目以后更好的发展迭代,打算…

    Java 2023年6月14日
    0137
  • SpringCloud微服务实战——搭建企业级开发框架(四十二):集成分布式任务调度平台XXL-JOB,实现定时任务功能

    定时任务几乎是每个业务系统必不可少的功能,计算到期时间、过期时间等,定时触发某项任务操作。在使用单体应用时,基本使用Spring提供的注解即可实现定时任务,而在使用微服务集群时,这…

    Java 2023年6月9日
    0105
  • JFinal 1.5 发布,JAVA极速WEB+ORM框架

    JFinal 爱好者一直都在问 JFinal 何时再次升级?JFinal 1.5 何时发布?以往升级都保持在每月近两次的频率,为何本次五个月过去了新版本还不出?由于作者暂时阔别码坛…

    Java 2023年5月29日
    098
  • 理解Java注解类型

    一. 理解Java注解 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态…

    Java 2023年5月29日
    070
  • 旅游线路查询

    旅游线路查询—参数传递 header.html页面: //给搜索按钮绑定单击事件,获取搜索输入框的内容 $("#search-button").click(fu…

    Java 2023年6月6日
    0123
  • 将宝塔PHP项目下载到本地部署之nginx配置

    最近,公司人手不够,找外包团队做了个项目,php做的,对方测试是部署到宝塔上的。 对方做方,直接将宝塔上代码下载下来丢给了我们。 项目做的超级烂,服务态度还很差。主要是我们提前把款…

    Java 2023年5月30日
    085
  • 5种高大上的yml文件读取方式,你知道吗?

    原创:微信公众号 &#x7801;&#x519C;&#x53C2;&#x4E0A;,欢迎分享,转载请保留出处。 在上一篇文章中,我们从源码角度分析了…

    Java 2023年6月5日
    0132
  • 开发思想

    解决的问题:一类对象,不同对象有不同的处理 顶级接口 定义规范,面向接口编程 抽象策略 定义一套模板,不同的交给不同的策略实现 具体策略 枚举 对象标识 –具体策略 策…

    Java 2023年6月14日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球