【算法思考记录】力扣2730. 找到最长的半重复子字符串【Python3、滑动窗口】

原题链接


滑动窗口技巧详解

什么是滑动窗口

滑动窗口是一种常用的算法技巧,适用于处理数组、字符串等序列数据的子集或子串的问题。它通过维护一个窗口(通常是两个指针表示的区间),在遍历的过程中实现窗口的滑动,从而解决特定问题。

滑动窗口的基本思想

  1. 定义窗口的起始位置和结束位置:通过两个指针(通常是leftright)定义窗口的起始和结束位置。

  2. 动态调整窗口大小:随着遍历的进行,通过移动指针动态调整窗口的大小,以适应问题的要求。

  3. 实时更新结果:在窗口滑动的过程中,实时更新问题的结果,通常是最大值、最小值、子串长度等。

滑动窗口的应用场景

滑动窗口技巧广泛应用于以下类型的问题:

  • 子数组/子串问题:求解最大、最小或满足特定条件的子数组或子串。

  • 子序列问题:求解最长、最短或满足特定条件的子序列。

  • 固定大小的窗口问题:例如计算窗口内的平均值、求和等。

  • 字符串匹配问题:在两个字符串中寻找匹配的子串。

滑动窗口的步骤

  1. 初始化窗口:定义两个指针,分别表示窗口的起始位置和结束位置。初始化其他必要的变量,如结果变量。

  2. 遍历序列:使用右指针进行遍历,扩展窗口。

  3. 更新窗口:根据问题的要求,通过移动左指针或右指针,动态调整窗口的大小。

  4. 实时更新结果:在窗口滑动的过程中,实时更新问题的结果。

  5. 返回结果:返回最终结果。

示例:最长半重复子字符串问题的解法

class Solution:
    def longestSemiRepetitiveSubstring(self, s: str) -> int:
        left = 0
        n = len(s)
        ans = 1
        pair = 0
        for right in range(1, n):
            if s[right] == s[right - 1]:
                pair += 1
                while pair > 1:
                    left += 1
                    if s[left] == s[left - 1]:
                        pair -= 1

            ans = max(ans, right - left + 1)
        return ans

在这个示例中,我们使用滑动窗口技巧解决了最长半重复子字符串的问题。通过维护两个指针leftright,动态调整窗口大小,并实时更新最终结果ans,最终得到问题的解答。

滑动窗口技巧是解决一类问题的通用方法,通过合理设计窗口的滑动规则,可以高效地解决多种问题。

找到最长的半重复子字符串

问题描述

给定一个下标从0开始的字符串s,该字符串仅包含0到9的数字字符。如果一个字符串t中至多有一对相邻字符是相等的,那么称这个字符串t是半重复的。例如,“0010”、“002020”、“0123”、"2002"和"54944"是半重复字符串,而"00101022"和"1101234883"不是。请你返回s中最长半重复子字符串的长度。

一个子字符串是一个字符串中一段连续非空的字符。

示例

示例1:

输入: s = “52233”
输出: 4
解释: 最长半重复子字符串是 “5223”,子字符串从i = 0开始,在j = 3处结束。

示例2:

输入: s = “5494”
输出: 4
解释: s就是一个半重复字符串,所以答案为4。

示例3:

输入: s = “1111111”
输出: 2
解释: 最长半重复子字符串是 “11”,子字符串从i = 0开始,在j = 1处结束。

提示:

  • 1 <= s.length <= 50
  • ‘0’ <= s[i] <= ‘9’

解决方案

class Solution:
    def longestSemiRepetitiveSubstring(self, s: str) -> int:
        left = 0
        n = len(s)
        ans = 1
        pair = 0
        for right in range(1, n):
            if s[right] == s[right - 1]:
                pair += 1
                while pair > 1:
                    left += 1
                    if s[left] == s[left - 1]:
                        pair -= 1

            ans = max(ans, right - left + 1)
        return ans

详细步骤解析

  1. 初始化指针left为0,字符串长度ns的长度,初始化最终结果ans为1,pair为0,用于记录相邻字符相等的对数。

  2. 使用指针right从1到n-1进行遍历,表示当前字符的下标。

  3. 如果s[right]等于s[right - 1],说明找到相邻字符相等的一对,此时pair加1。

  4. 进入while循环,当pair大于1时,表示有多余的相邻字符相等的对数,需要移动left指针。

  5. 在while循环中,每次移动left指针,如果s[left]等于s[left - 1],说明当前位置也是相邻字符相等的一对,此时pair减1。

  6. 在遍历的过程中,更新最终结果ans为当前窗口的长度right - left + 1的最大值。

  7. 返回最终结果ans,即最长半重复子字符串的长度。

该算法使用同向双指针的技巧,通过维护一个窗口,动态更新窗口的起始位置left,以及统计相邻字符相等的对数pair,最终得到最长半重复子字符串的长度。

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值