784. 字母大小写全排列
给定一个字符串
S
,通过将字符串S
中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。示例: 输入: S = "a1b2" 输出: ["a1b2", "a1B2", "A1b2", "A1B2"] 输入: S = "3z4" 输出: ["3z4", "3Z4"] 输入: S = "12345" 输出: ["12345"]
注意:
S
的长度不超过12
。S
仅由数字和字母组成。
解法一
class Solution {
public:
void build(vector<string>& res, int ptag, string str) {//ptag 是父结点的标号
if(str.empty()) return;
int i;
for(i = 0; i < str.size(); i++) {
if(str[i] >= 'a' && str[i] <= 'z' || str[i] >= 'A' && str[i] <= 'Z') break;
}
res[ptag - 1] += str.substr(0, i);
if(i == str.size()) return;
if(ptag * 2 >= res.size()) res.resize(res.size() * 2 + 1);
char c = str[i] >= 'a' && str[i] <= 'z' ? str[i] : str[i] + 32;
res[ptag * 2 - 1] = res[ptag - 1] + c;
res[ptag * 2] = res[ptag - 1] + (char)(c - 32);
build(res, ptag * 2, str.substr(i + 1));
build(res, ptag * 2 + 1, str.substr(i + 1));
}
vector<string> letterCasePermutation(string S) {
vector<string> tree(1, ""), res;
build(tree, 1, S);
int nt = tree.size(), ns = S.size();
for(int i = 0; i < nt; i++) {
if(tree[i].size() == ns) res.push_back(tree[i]);
}
return res;
}
};
解法二
class Solution {
public:
vector<string> letterCasePermutation(string S) {
vector<string> res(1, "");
for(char c : S) {
if(c >= '0' && c <= '9') {
for(string& str : res) str += c;
}
else {
int n = res.size();
for(int i = 0; i < n; i++) {// len * 2
res.push_back(res[i]);
res[i] += c;
res[i + n] += c ^ 32;//按位异或, 改变大小写
}
}
}
return res;
}
};
解法一使用一个数组模拟了一棵前缀树,使用递归法构建完成后,再遍历一次数组,取出其叶子结点的值存入res并返回。
解法二同样使用了一个数组res,但是简化了许多。遍历一次字符串S,在遍历过程中:
- 如果c是数字,就对res的每个元素后追加该字符;
- 如果c是字母,就将res的大小翻倍,对改变大小前的每个元素后追加字符c,对翻倍新产生的元素后追加字符c ^ 32(反转大小写的技巧,对于大写就相当于加32,对于小写就相当于减32)。
- 遍历完成,返回res。
2019/07/04 14:40