双指针问题的算法

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

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

一些题目

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

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)

大家都在看

  • Java_GUI

    Java_GUI 1.GUI概述 图形用户界面( Graphical User Interface,简称 GUI,又称 图形用户接口)是指采用图形方式显示的计算机操作用户界面。 […

    Java 2023年6月9日
    087
  • 从IO到netty

    一、pageCache 1.FileOutputStream与BufferedOutputStream的主要区别 &#x7CFB;&#x7EDF;&#x8C…

    Java 2023年6月9日
    080
  • SpringBoot配置文件优先级

    在开发过程中,不知道有没有这样的经历,项目实际读取的配置信息有时候总是与预期不符,今天就来研究下 SpringBoot 读取配置文件顺序。 一、SpringBoot 配置文件加载优…

    Java 2023年6月5日
    076
  • Mybatis系列全解(一):手写一套持久层框架

    Mybatis系列全解(一):手写一套持久层框架 Mybatis系列全解(一):手写一套持久层框架 Mybaits系列全解 (持续更新) 一、JDBC是谁? + * –…

    Java 2023年6月7日
    082
  • Redis 学习笔记之动态字符串(SDS)

    Redis 学习笔记之动态字符串(SDS) SDS(simple dynamid string) 一、Redis 的 String 的基本概念 1.1 二进制安全 Redis St…

    Java 2023年6月5日
    083
  • 会话技术 cookie 和 Session(1)

    CookieCookie 属于客户端会话技术,它是服务器发送给浏览器的小段文本信息,存储在客户端浏览器的内存中或硬盘上。当浏览器保存了Cookie 后,每次访问服务器,都会在HTT…

    Java 2023年6月9日
    091
  • 从Spring框架看设计模式如何灵活使用

    Singleton 单例模式 单例模式是确保每个应用程序只存在一个实例的机制。默认情况下,Spring将所有bean创建为单例。 你用@Autowired获取的bean,全局唯一。…

    Java 2023年5月30日
    077
  • Java并发相关知识点梳理和研究

    知识点思维导图 (图比较大,可以右键在新窗口打开) 经典的wait()/notify()/notifyAll()实现生产者/消费者编程范式深入分析 & synchroniz…

    Java 2023年5月29日
    069
  • 动力节点-王妈妈Springboot教程(三)Spring Boot和web组件

    第三章 Spring Boot 和 web 组件 *笔记中的视频观看地址 https://www.bilibili.com/video/BV1XQ4y1m7ex 3.1 Sprin…

    Java 2023年6月7日
    0106
  • 学生成绩管理系统【c】

    include Original: https://www.cnblogs.com/java20130723/p/3211444.htmlAuthor: 程序流程图Title: 学…

    Java 2023年5月29日
    067
  • java中远程调用第三方接口

    一、概述 在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适。很多项目都会封装规定好本身项目的接口规范,所以大多数需要去调用对方提供的接口或第三方接口(短信…

    Java 2023年5月29日
    077
  • Java基础知识26–Java 异常;异常抛出后代码的执行情况

    1. Java 异常 异常是指阻止当前方法或者作用域继续执行的问题。异常处理机制就是当程序发生异常时,它强制终止程序运行,记录异常信息并将这些信息反馈给我们,由我们来确定是否处理异…

    Java 2023年5月29日
    0119
  • 设计模式之外观模式

    本文通过老王改造小王公司的整体架构来说明外观模式,所谓的外观模式其实就是在各种复杂的子系统中抽象出来一个接口,隐藏具体的实现细节,调用方调用时只需要调用接口即可。为了加深理解我们会…

    Java 2023年6月8日
    091
  • Activemq消息类型

    Activemq消息类型JMS规范中的消息类型包括TextMessage、MapMessage、ObjectMessage、BytesMessage、和StreamMessage等…

    Java 2023年5月29日
    053
  • Nginx-正向代理实现

    正向代理简介 nginx不仅可以做反向代理,还能用作正向代理来进行上网等功能。如果把局域网外的 Internet想象成一个巨大的资源库,则局域网中的客户端要访问 Internet,…

    Java 2023年5月30日
    089
  • Spring知识点总结3 Spring框架

    什么是 Spring 框架? Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性。 我们一般说 Spring 框架指的都是 Spri…

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