LeetCode2981 找出出现至少三次的最长特殊子字符串 I(Pythohn)

题目

2981/2982. 找出出现至少三次的最长特殊子字符串 I/II

问题描述

给你一个仅由小写英文字母组成的字符串 s 。

如果一个字符串仅由单一字符组成,那么它被称为 特殊 字符串。例如,字符串 “abc” 不是特殊字符串,而字符串 “ddd”、“zz” 和 “f” 是特殊字符串。

返回在 s 中出现 至少三次 的 最长特殊子字符串 的长度,如果不存在出现至少三次的特殊子字符串,则返回 -1 。

子字符串 是字符串中的一个连续 非空 字符序列。
示例 1:

输入:s = “aaaa”
输出:2
解释:出现三次的最长特殊子字符串是 “aa” :子字符串 “aaaa”、“aaaa” 和 “aaaa”。
可以证明最大长度是 2 。
示例 2:

输入:s = “abcdef”
输出:-1
解释:不存在出现至少三次的特殊子字符串。因此返回 -1 。
示例 3:

输入:s = “abcaba”
输出:1
解释:出现三次的最长特殊子字符串是 “a” :子字符串 “abcaba”、“abcaba” 和 “abcaba”。
可以证明最大长度是 1 。

提示:

3 <= s.length <= 50
s 仅由小写英文字母组成。

方法一

解题思路

暴力求解:遍历所有子串,找到出现三次的最长特殊子串

算法过程

  1. 定义一个字典,存储特殊子串出现的次数
  2. 从最大长度的子串开始查找,由于子串至少要有三个,最长子串长度l为len(s)-2
  3. 已知子串长度,将子串左端从0开始遍历,当左端为0,右端为l,直到右端为字符串末尾截止。判断子串是否为特殊子串,是则统计到字典中,特殊子串个数大于等于3返回长度。
  4. 不满足3返回-1

代码编写

class Solution:
    def maximumLength(self, s: str) -> int:
        word_count = defaultdict(lambda: 0)
        for l in range(len(s)-2,0,-1):
            right = l
            left = 0
            while right <= len(s):
                s1 = s[left:right]
                if s1.count(s1[0]) == len(s1):
                    word_count[s1] += 1
                if word_count[s1] == 3:
                    return l
                left+=1
                right+=1
        return -1

复杂度分析

时间复杂度:O(n^2)
空间复杂度:O(n^2)

方法二

解题思路

遍历一遍字符串,统计每一段连续的特殊子串中字母出现的次数
如aabcccaaabbaa
a:[2,3,2]
b:[1,2]
c:[3]
排序每一个字母中的列表,从大到小
a:[3,2,2]
出现三次的最长子串肯定在列表前三个当中
1.长度a[0]-2子串有3个
2.长度a[0]-1有两个,加上a[1]一个,至少有三个
3.长度a[2]有一个,加上a[0]、a[1],至少有三个
ans=max(a[0]-2,min(a[0]-1,a[1]),a[2])

算法过程

代码编写

class Solution:
    def maximumLength(self, s: str) -> int:
        word_count = defaultdict(list)
        cnt = 0
        for i,c in enumerate(s):
            cnt+=1
            if i+1 == len(s) or s[i+1] != c:
                word_count[c].append(cnt)
                cnt = 0
        ans = 0
        for c in word_count.values():
            c.sort(reverse=True)
            c.extend([0,0])
            ans = max(ans,c[0]-2,min(c[0]-1,c[1]),c[2])
        return ans if ans else -1

复杂度分析

时间复杂度:O(nlog(n))
空间复杂度:O(n)

方法三

解题思路

遍历一遍字符串,统计每一段连续的特殊子串中字母出现的次数
如aabcccaaabbaa
a:[2,3,2]
b:[1,2]
c:[3]
对每一个列表进行二分查找其长度
取s的中位数为初始长度,检测满足该长度下的连续字符串个数,满足则存储长度并增加长度,不满足则缩小长度。

算法过程

代码编写

class Solution:
    def maximumLength(self, s: str) -> int:
        words = defaultdict(list)
        cnt = 0
        for i,c in enumerate(s):
            cnt+=1
            if i+1==len(s) or c!=s[i+1]:
                words[c].append(cnt)
                cnt = 0
            
        res = -1
        for vec in words.values():
            left, right = 1, len(s) - 2 # 字符串s
            while left <= right:
                mid = (left + right) // 2
                count = 0
                for x in vec: # 单个字符连续个数列表
                    if x >= mid: # 判断是否比当前字符串的一半长
                        count += x - mid + 1 # 获取mid长度下,连续字符串的个数
                if count >= 3: # 该长度下个数大于等于3,长度符合条件
                    res = max(res, mid)
                    left = mid + 1 # 增加长度
                else:
                    right = mid - 1 # 减少长度
        return res

复杂度分析

时间复杂度:O(nlog(n))
空间复杂度:O(n)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Baal Austin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值