至少有k个重复字符的最长子串

题目

找到给定字符串(由小写字符组成)中的最长子串 T ,?要求?T?中的每一字符出现次数都不少于 k 。输出 T?的长度。
示例 1:
输入:
s = “aaabb”, k = 3
输出:
3
最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。

	示例 2:
	输入:
	s = "ababbc", k = 2
	输出:
	5
	最长子串为 "ababb" ,其中 'a' 重复了 2 次, 'b' 重复了 3 次。

分析

首先是统计每个字母出现的次数,然后根据要求k来调整滑窗的边界。滑窗边界初次调整结束后,需要再次调整
	因为内部可能存在重复次数小于k的字母,如果找到,以这个字母为中心,划分成两个滑窗,然后进行递归并每
	个滑窗二者中值最大的一个。

技术点附注:
1.首先是统计每个字母出现的次数,这个可以用unoredered_map。
2.其次由于需要统计最长子串长度,所以还需要一个滑窗,这个滑窗由于需要计算长度,所以需要设置一个
right和left。不像之前最长无重复子串问题,只需要确认一边即可。
3.如果初次调整后,字符串中间若出现不符合要求的情况,我们需要分隔两段继续找,这种情况优先考虑递归。
并且选择二者中最大的一个,需要记得用max函数

#include<unordered_map>
#include<string>
#include<algorithm>

using namespace std;

class MyClass
{
public:
	int longestSubstring(string s, int k) {
		int left = 0, right = s.size() - 1;
		return slideWindows(s, k, left, right);
	}

	int slideWindows(string s, int k, int left, int right){
		if (left > right){
			return 0;
		}

		unordered_map<char, int> cnt;
		for (int i = left; i <= right; ++i){
			if (cnt[s[i]] < 0){
				cnt[s[i]] = 1;
			}
			else{
				++cnt[s[i]];
			}
		}
		
		while (left <= right&&cnt[s[left]] < k)
		{
			cnt[s[left]]--;
			++left;
		}

		while (left <= right&&cnt[s[right]] < k)
		{
			cnt[s[right]]--;
			--right;
		}

		for (int i = left + 1; i < right; ++i)
		{
			if (cnt[s[i]] < k){
				return max(slideWindows(s, k, left, i - 1), slideWindows(s, k, i + 1, right));
			}
		}

		return right - left + 1;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值