力扣每日一题20220207
题目简述
如果字符串中不含有任何 ‘aaa’,‘bbb’ 或 ‘ccc’ 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。
给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。 s 中 最多 有a 个字母 ‘a’、b 个字母 ‘b’、c 个字母 ‘c’ 。 s 中只含有
‘a’、‘b’ 、‘c’ 三种字母。 如果不存在这样的字符串 s ,请返回一个空字符串
其中,0 <= a, b, c <= 100
a + b + c > 0""。
题解:根据本题的题意,很容易想到了深度优先搜索的算法,即dfs+剪枝,此时的算法时间复杂度应该为O(3^max(a,b,c))但是很遗憾,由于参数a,b,c的范围使得该算法的执行时间较慢,导致最终结果为TLE。
代码为:
class Solution {
public:
string ans;
int Max;
string x;
int num[3];
string longestDiverseString(int a, int b, int c) {
map<char, int> s;
s['a'] = 1;
s['b'] = 1;
s['c'] = 1;
Max = 0;
ans = "";
x = "";
num[0] = a;
num[1] = b; num[2] = c;
getLong(s,-1);
return ans;
}
void getLong(map<char, int> s,int alpha)
{
int i;
if (s['a'] == 3)
{
if (Max < x.length())
{
Max = x.length()-1;
ans = x.substr(0,x.length()-1);
}
return;
}
if (s['b'] == 3)
{
if (Max < x.length())
{
Max = x.length() - 1;
ans = x.substr(0, x.length() - 1);
}
return;
}
if (s['c'] == 3)
{
if (Max < x.length())
{
Max = x.length() - 1;
ans = x.substr(0, x.length() - 1);
}
return;
}
for (i = 0; i < 3; i++)
if (num[i] != 0)
break;
if (i == 3) {
Max = x.length();
ans = x;
return;
}
for (int i = 0; i < 3; i++)
{
if (num[i] > 0)
{
num[i]--;
if (x.length() != 0 && x[x.length() - 1] - 'a' == i)
s['a' + i]++;
else if (x.length() != 0) {
s['a' + i] = 1;
}
x += 'a' + i;
getLong(s,i);
x = x.substr(0, x.length() - 1);
if (x.length() != 0 && x[x.length() - 1] - 'a' == i)
s['a' + i]--;
num[i]++;
}
}
}
};
执行结果为:
最后发现,这并不是一道dfs,而是一道贪心!!!
可以先看本题的题目条件:
- 每个字母的连续个数不能超过3个;
- 字母的个数有限
而最终所需要得到的结果则是最长的字符串,因此很容易可以想到贪心策略:
个数较少的字母用于当做隔离字母,个数较多的字母优先排列;如果发现当前的字母个数超过了3个,则跳过当前字母,直到找到当前的可以添加的字母为止;若已经找不到当前可以添加的字母,则退出。
代码为:
class Solution {
public:
class mycomp2 {
public:
bool operator() (pair<char, int> a, pair<char, int> b) {
return (a.second > b.second);
}
};
string longestDiverseString(int a, int b, int c) {
string ans;
vector<pair<char, int>> s = { {'a',a},{'b',b},{'c',c} };
while (1) {
bool flag = false;
sort(s.begin(), s.begin()+s.size(), mycomp2());
for (vector<pair<char, int>>::iterator it = s.begin(); it != s.end(); it++) {
int m = ans.size();
char ch = (*it).first;
int freq = (*it).second;
if (freq <= 0)
break;
if (m >= 2 && ans[m - 2] == ch && ans[m - 1] == ch)
continue;
ans.push_back(ch);
flag = 1;
(*it).second--;
break;
}
if (!flag)
break;
}
return ans;
}
};
最终运行结果为:
采用贪心,则时间复杂度大大降低,主要的时间是在排序上,若采用sort函数,则时间复杂度为O((a+b+c)×ClogC)。
总览这道题,发现采用暴力算法并没有很好的完成这道题,很容易TLE;还是需要多多锻炼贪心或者dp的逻辑思维哇!