【LeetCode 每日一题】1156. 单字符重复子串的最大长度

82 阅读2分钟

1156. 单字符重复子串的最大长度

难度:中等

时间:2023/06/03


如果字符串中的所有字符都相同,那么这个字符串是单字符重复的字符串。

给你一个字符串 text,你只能交换其中两个字符一次或者什么都不做,然后得到一些单字符重复的子串。返回其中最长的子串的长度。

示例 1:

输入:text = "ababa"
输出:3

示例 2:

输入:text = "aaabaaa"
输出:6

示例 3:

输入:text = "aaabbaaa"
输出:4

示例 4:

输入:text = "aaaaa"
输出:5

示例 5:

输入:text = "abcdef"
输出:1

提示:

  • 1 <= text.length <= 20000
  • text 仅由小写英文字母组成。

解题思路:

要求计算重复子串相关的题,优先想到双指针。这题可以使用一次遍历+双指针进行求解。

首先统计text字符串中每个单词出现的次数; 然后遍历数组,假设遍历到当前元素i的值为a,使用双指针计算i后连续的且与a相同的元素个数,若该个数小于a在text中出现的总次数,说明可以将一个a交换过来,从而得到更长的一段仅包含字符 a 的子串。交换后,交换过来的 a 可能会使得两段连续的 a 拼接在一起,拼接后连续 a 长度即为 a 的最长子串长度。 通过一次遍历后返回所有字符中最长子串长度最大的那一个。

class Solution:
    def maxRepOpt1(self, text: str) -> int:
        ans = 1
        cnt = Counter(text)
        for i in range(26):
            ch = chr(ord('a') + i)
            l, t, mid = 0, 0, 0
            for r, x in enumerate(text):
                if x != ch:
                    t += 1
                    if t == 1:
                        mid = r
                if t < 2:
                    ans = max(ans, min(r - l + 1, cnt[ch]))
                else:
                    t -= 1
                    l = mid + 1
                    mid = r
        return ans

总结: 本题的难点是交换一个字符后可以继续搜索,所以大致有两种情况,一个是当前最长的相同字符串,另一个是当前的长度,跳过一个不同的,再加上下一个相同字符串。采取贪心的做法,第二种情况的长度肯定不小于第一种情况,所以,结果只取第二种情况的长度。用了一个新的指针k,去搜索第二个可能的字符串的长度。更新结果的时候,结果不会超过当前字符的总数量,这是最巧妙的地方,相当于贪心的去搜索可能的最长的长度,但有效的最大值只能是字符的数量。

用的是常规的滑动窗口,i 是起始位置,j 是下一个起始位置/第一个不同的字符的位置/当前连续相同字符串的下一个位置/字符串的末端的下一个位置。 本题的难点是交换一个字符后可以继续搜索,所以大致有两种情况,一个是当前最长的相同字符串,另一个是当前的长度,跳过一个不同的,再加上下一个相同字符串。采取贪心的做法,第二种情况的长度肯定不小于第一种情况,所以,结果只取第二种情况的长度。用了一个新的指针k,去搜索第二个可能的字符串的长度。更新结果的时候,结果不会超过当前字符的总数量,这是最巧妙的地方,相当于贪心的去搜索可能的最长的长度,但有效的最大值只能是字符的数量。