leetcode.2014 重复k次的最长子序列

题目描述

解题思路

这一题本来怎么才能获得通用因为乍一看感觉遍历时间代价非常直到后面看到提示

提示里面专门包含一个n < k * 8,这太反常了。后面仔细一想,有道理,最后答案的字符个数一定小于8,因为 字符 k一定小于字符串长度否则这个候选一定无法重复k

那么直接给了遍历信心

直接遍历2字母组合开始遍历直到8为止,满足条件候选尝试接第三个候选字符,第四个候选字符,直到接不了任何字母为止至于能否重复k直接遍历字符看看目前候选是否k

唯一需要关注哪些过滤条件

  • 首先每个字母出现频率进行次数统计
  • 候选每个字母出现频率必须>=k
  • 字符串每次匹配一次候选时候都要判断候选字符剩余个数能否支持k重复
  • 添加候选字符如果目前候选解里面包含这个候选字符添加候选字符字符候选个数m那么cnt[候选字符] >= m * k理论可以这样加速,但我懒没有实现)
  • 添加候选字符字典序优先添加这样返回结果直接返回candidate[0]就可以加速

代码

string longestSubsequenceRepeatedK(string s, int k) {
	vector<int> cnt;
	vector<string> candidate;
	cnt.resize(26);
	for(int i = 0; i < s.size(); i++)
	{
		cnt[s[i] - 'a'] ++;
	}
	
	for(int i = 25; i >= 0; i--)
	if(cnt[i] >= k)
	candidate.emplace_back(string(1,i + 'a'));	
	for(int num = 2; num < 8; num++)
	{
	vector<string> new_candidate;
	for(int i = 0; i < candidate.size(); i++)
	{
		int remain = 0;
		char last = candidate[i].size() - 1;
		
		for(int q = 25 ; q >= 0; q--)
		{
			remain = cnt[q];
			if(remain < k) continue;
			int curr_idx = 0;
			int curr_k = k;
			bool flag = true;
			for(int idx = 0; idx < s.size(); idx ++)
			{
				if(flag && s[idx] == candidate[i][curr_idx])
				{
					if(curr_idx == last)
					{
						if(s[idx] == q + 'a') remain--;
						if(remain < curr_k)
						break;
						curr_k --;
						if(curr_k == 0)
						{
							new_candidate.emplace_back(candidate[i]+ char(q + 'a'));
							break;
						}
						flag = false;
						continue;
					}
					curr_idx = (curr_idx + 1)% candidate[i].size();
				}
				if(s[idx] == q + 'a')
				{
					remain --;
					if(!flag)
					{
						curr_idx = 0;
						flag = true;
					}
				}
			}
		}	
	}
	if(new_candidate.empty()) break;
	candidate.swap(new_candidate);
	}
	if(candidate.empty()) return "";
	return candidate[0];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值