Skip to content

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

给你一个下标从 0 开始的字符串 s ,这个字符串只包含 0 到 9 的数字字符。

如果一个字符串 t 中至多有一对相邻字符是相等的,那么称这个字符串 t 是 半重复的 。例如,"0010" 、"002020" 、"0123" 、"2002" 和 "54944" 是半重复字符串,而 "00101022" (相邻的相同数字对是 00 和 22)和 "1101234883" (相邻的相同数字对是 11 和 88)不是半重复字符串。

请你返回 s 中最长 半重复 子字符串 的长度。

示例 1:
输入:s = "52233"
输出:4
解释:
最长的半重复子字符串是 "5223"。整个字符串 "52233" 有两个相邻的相同数字对 22 和 33,但最多只能选取一个。

示例 2:
输入:s = "5494"
输出:4
解释:
s 是一个半重复字符串。

示例 3:
输入:s = "1111111"
输出:2
解释:
最长的半重复子字符串是 "11"。子字符串 "111" 有两个相邻的相同数字对,但最多允许选取一个。

解题思路

输入:一个仅包含数字(0–9)的字符串 s

输出:返回最长的“半重复字符串”的长度 —— 即最多只包含一对相邻重复字符的连续子串

本题属于 可变长度滑动窗口类型 类型。

我们可以使用双指针维护一个滑动窗口,并用一个变量 repeat_count 记录当前窗口中出现了多少对相邻重复字符。当窗口内重复对超过 1 个时,即不满足“半重复”要求,此时需要不断移动左指针缩小窗口,直到窗口重新合法。

在窗口合法的前提下,每次记录当前窗口的长度,并更新最大值。最终返回整个过程中出现的最大合法窗口长度(注意至少为 1)。

代码实现

python
class Solution:
    def longestSemiRepetitiveSubstring(self, s: str) -> int:
        left = 0                  # 滑动窗口左边界
        repeat_count = 0          # 当前窗口内相邻重复对的数量
        max_len = 1               # 最长合法子串长度,至少为1

        # 从第二个字符开始扫描,right 是窗口右边界
        for right in range(1, len(s)):
            # 如果当前字符和前一个字符相同,说明出现了一个相邻重复对
            if s[right] == s[right - 1]:
                repeat_count += 1

            # 如果重复对超过1个,缩小窗口(移动左边界)
            while repeat_count > 1:
                if s[left] == s[left + 1]:
                    repeat_count -= 1
                left += 1  # 缩小左边界

            # 更新当前窗口的最大长度
            max_len = max(max_len, right - left + 1)

        return max_len  # 返回最长合法子串长度

复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)

链接

2730 国际版

2730 中文版