题目来源:力扣
题目介绍:
给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。
=========================================================
示例:
输入: S = “a1b2”
输出: [“a1b2”, “a1B2”, “A1b2”, “A1B2”]
输入: S = “3z4”
输出: [“3z4”, “3Z4”]
输入: S = “12345”
输出: [“12345”]
==========================================================
审题:
分析题目,发现与之前做过的一道题幂集非常相似.其解题思路也大致一致.在幂集中,当前字符有两种可能,包括在最终子集字符串中,或不包括在其中.而在该问题中,如果字符为数字,则其仅有一种可能,如果为字母,则有两种可能,小写字母或对应的大小字母.参照幂集的解题思路,我们使用回溯法与位向量法.在此基础上,我们也提出迭代法.
- 回溯法思路与幂集完全一致,此处不再缀述.
- 对于位向量法,由于数字无法进行大小写变化,因此只有一种可能.对于包含n个字母的字符串,其字母大小写全排列共有 2 n 2^n 2n个字符串,因此我们的位向量仅用于表示当前字符串的字母位,如果当前位为0,则使用小写字母,如果为1,则使用大写字母.
- 对于该问题,我们也可以使用迭代法构建全排列结果.考虑,如果我们已经构建了前k个字符的全排列,则前k+1个字符的全排列该如何构建?如果第k+1个字符是数字,我们仅需将第其添加到原有的k个字符全排列中的所有字符串结尾即可,如果第k+1个字符是字母,则我们需要将当前字母的大小写分别添加到原有的全排列字符串之后,为此我们对原有全排列中的每一个字符串复制一个副本,并向原字符串添加第k+1个字符的小写,向副本中添加第k+1个字符对应的大写即可.
java算法
回溯法:
class Solution {
private void dfs(String S, String curS, List<String> list){
if(curS.length() == S.length()){
list.add(curS);
return;
}
char c = S.charAt(curS.length());
if(Character.isLetter(c)){
dfs(S, curS+Character.toLowerCase(c), list);
dfs(S, curS+Character.toUpperCase(c), list);
}
else
dfs(S, curS+c, list);
}
public List<String> letterCasePermutation(String S) {
List<String> list = new LinkedList<>();
dfs(S, "", list);
return list;
}
}
位向量法:
class Solution {
public List<String> letterCasePermutation(String S) {
//统计当前字符串中的字母个数
int B = 0;
for(char c: S.toCharArray()){
if(Character.isLetter(c))
B++;
}
List<String> list = new ArrayList<>();
for(int i = 0; i < 1 << B; i++){
int b = 0; //统计当前移位个数
StringBuilder s = new StringBuilder();
for(char c: S.toCharArray()){
if(Character.isLetter(c)){
if(((i >> b++) & 1) == 1)
s.append(Character.toLowerCase(c));
else
s.append(Character.toUpperCase(c));
}
else
s.append(c);
}
list.add(s.toString());
}
return list;
}
}
迭代法:
class Solution {
//迭代方法
public List<String> letterCasePermutation(String S) {
List<StringBuilder> list = new ArrayList<>();
list.add(new StringBuilder());
for(char c: S.toCharArray()){
int n = list.size();
boolean isChar = Character.isLetter(c);
for(int i = 0; i < n; i++){
if(isChar){
//如果是字母,则对每一个既有字符串,拷贝一个,然后给原字符串添加小写字母,给拷贝字符串添加大写字母
list.add(new StringBuilder(list.get(i)));
list.get(i).append(Character.toLowerCase(c));
list.get(n+i).append(Character.toUpperCase(c));
}
else{
list.get(i).append(c);
}
}
}
List<String> strList = new ArrayList<>();
for(StringBuilder s: list)
strList.add(s.toString());
return strList;
}
}