力扣784. 字母大小写全排列 回溯法 C++递归和非递归俩种实现非方式
Posted weixin_43739821
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣784. 字母大小写全排列 回溯法 C++递归和非递归俩种实现非方式相关的知识,希望对你有一定的参考价值。
给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。
示例:
输入:S = "a1b2"
输出:["a1b2", "a1B2", "A1b2", "A1B2"]
输入:S = "3z4"
输出:["3z4", "3Z4"]
输入:S = "12345"
输出:["12345"]
提示:
S 的长度不超过12。
S 仅由数字和字母组成。
思路:
观察题意可知,我们只需要找出字符串中的k个字母,然后将k个字母中分别选取0~k个改变大小写就行,选取0个则是原字符串,选取k个则是将字符串中的字母全部转换大小写,选取x(x>0&&x<k)则需要在k个字母中选x个字母转换大小写,这本质上是一种排列组合,但其实我们不需要将问题想的那么复杂,我们可以将每个字母看成一个分支,每遇到一个字母将产生一个分支,一个大写的分支一个小写的分支,当字符串中有k个字母,一共有k个分支,产生2^k种组合方式。
ps:改变字母大小写有技巧,只需要执行:
char zimu = 'a';
zimu ^= (1 << 5);//位运算yyds
递归实现:
深度优先搜索,不断产生搜索可能性,我们从第0位字符开始递归到第n-1位字符,若该位字符为数字,则直接进入下一次递归,若是字母,则要分大小写递归,此时产生分支。当递归到n位,说明已经遍历完所有字符,将该字符串加入列表。此方法本质为回溯法。
void dfs(string s, int n, vector<string>& res) {//从上往下递归
if (s.size() == n) return res.push_back(s);//递归完成标志
if (isdigit(s[n])) return dfs(s, n + 1, res);
//isigit()函数判断字符是否为数字,这里如果是数字直接跳过
dfs(s, n + 1, res);//不是数字,分大小写递归
s[n] ^= (1 << 5);//回溯
dfs(s, n + 1, res);
}
vector<string> letterCasePermutation(string S) {//求全排列
vector<string> res;
dfs(S, 0, res);
return res;
}
非递归实现:
我们遍历S,遇到字母就将列表中已有的字符串的这个字母全部转变大小写再加入其中。
vector<string> letterCasePermutation(string S) {
vector<string> result{S};//需要先将S加入列表
int n=S.size();
for (int i = 0; i < n; i++) {
if (isupper(S[i])) {//isupper()判断字符是否为大写字母
int size = result.size();
for (int j = 0; j < size; j++) {
string temp = result[j];
temp[i] = tolower(temp[i]);//tolower()函数将字符转变为小写
result.emplace_back(temp);
}
} else if (islower(S[i])) {//islower()判断字符是否为小写字母
int size = result.size();
for (int j = 0; j < size; j++) {
string temp = result[j];
temp[i] = toupper(temp[i]);//toupper()函数将字符转变为大写
result.emplace_back(temp);
}
}
}
return result;
}
以上是关于力扣784. 字母大小写全排列 回溯法 C++递归和非递归俩种实现非方式的主要内容,如果未能解决你的问题,请参考以下文章