
思路一:DFS
- 因为要输出所有的排列,所以要实打实得构造出每一个序列;
- 采用DFS依次向深遍历:
- 过程中对于字母元素修改其大小写,数字元素直接过;
- cur为当前正在构造的某一个答案。
Java
class Solution {
char[] ss;
List<String> res = new ArrayList<>();
int n;
char[] cur;
public List<String> letterCasePermutation(String s) {
ss = s.toCharArray();
n = s.length();
cur = new char[n];
DFS(0);
return res;
}
void DFS(int idx) {
if (idx == n) {
res.add(String.valueOf(cur));
return ;
}
cur[idx] = ss[idx];
DFS(idx + 1);
if (Character.isLetter(ss[idx])) {
cur[idx] = (char)(ss[idx]^32);
DFS(idx + 1);
}
}
}
- 时间复杂度:O(n×2n)
- 空间复杂度:O(n×2n)
C++
class Solution {
public:
vector<string> res;
string cur;
string s;
int n;
vector<string> letterCasePermutation(string s) {
this->s = s;
n = s.size();
cur = s;
DFS(0);
return res;
}
void DFS(int idx) {
if (idx == n) {
res.emplace_back(cur);
return ;
}
cur[idx] = s[idx];
DFS(idx + 1);
if (isalpha(s[idx])) {
cur[idx] = s[idx] ^ 32;
DFS(idx + 1);
}
}
};
- 时间复杂度:O(n×2n)
- 空间复杂度:O(n×2n)
思路二:二进制枚举
- 结果数量由原字符串s中字母数量m决定,所以用一个state表示每个字母的翻转状态,然后枚举每一种状态即可。
Java
class Solution {
public List<String> letterCasePermutation(String s) {
List<String> res = new ArrayList<String>();
int n = s.length(), m = 0;
for (int i = 0; i < n; i++)
m += Character.isLetter(s.charAt(i)) ? 1 : 0;
for (int state = 0; state < (1 << m); state++) {
char[] ss = s.toCharArray();
for (int i = 0, j = 0; i < n; i++) {
if (!Character.isLetter(ss[i]))
continue;
ss[i] = ((state >> j) & 1) == 1 ? (char)(ss[i]^32) : ss[i];
j++;
}
res.add(String.valueOf(ss));
}
return res;
}
}
- 时间复杂度:O(n×2n)
- 空间复杂度:O(n×2n)
C++
class Solution {
public:
vector<string> letterCasePermutation(string s) {
vector<string> res;
int n = s.size(), m = 0;
for (int i = 0; i < n; i++)
m += isalpha(s[i]) ? 1 : 0;
for (int state = 0; state < (1 << m); state++) {
string ss = s;
for (int i = 0, j = 0; i < n; i++) {
if (!isalpha(ss[i]))
continue;
ss[i] = ((state >> j) & 1) == 1 ? (char)(ss[i]^32) : ss[i];
j++;
}
res.emplace_back(ss);
}
return res;
}
};
- 时间复杂度:O(n×2n)
- 空间复杂度:O(n×2n)
总结
- 没写Rust之今天就是不想写
- 感觉也是半个暴力模拟题,复杂度贼高还没办法