题目链接:784. 字母大小写全排列 - 力扣(LeetCode)
题目:
给定一个字符串 s
,通过将字符串 s
中的每个字母转变大小写,我们可以获得一个新的字符串。
返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。
示例 1:
输入:s = "a1b2"
输出:["a1b2", "a1B2", "A1b2", "A1B2"]
示例 2:
输入: s = "3z4"
输出: ["3z4","3Z4"]
提示:
- 1 <= s.length <= 12
- s 由小写英文字母、大写英文字母和数字组成
思路:
使用回溯的思想,从左向右遍历字符串中每个字符:
- 如果该字符不是英文字母,直接跳过,检测下一个字符;
- 如果该字符是字母,转换大小写后,继续向后检测;当得到满足结束条件的序列后,将该字符恢复原来的大/小写状态,继续向后检测;
- 完成当前字符串搜索后,该序列即为要求的排列之一。
- 字母大小写转换可以通过与空格异或来实现
代码:
class Solution {
public List<String> letterCasePermutation(String s) {
List<String> res = new LinkedList<>();
char[] chars = s.toCharArray();
dfs(chars, 0, res);
return res;
}
public void dfs(char[] arr, int pos, List<String> res) {
//isDigit()判断数字,isLetter()判断字母,isLowerCase()判断是否是小写字母,isUpperCase()判断是否是大写字母
while (pos < arr.length && !Character.isLetter(arr[pos])) {//判断是否是字母,如果不是,直接向后走
pos++;
}
if (pos == arr.length) {//如果坐标走到了数组尾部,arr就是要求的子串之一l
res.add(String.valueOf(arr));
return;
}
dfs(arr, pos + 1, res);
//if (arr[pos] >= 'a' && arr[pos] <= 'z') arr[pos] -= 32;//大写转小写,小写转大写
//else if (arr[pos] >= 'A' && arr[pos] <= 'Z') arr[pos] += 32;
//可变元素类型中,x+=1是改变自身的值,而x=x+1是创建了一个同名变量,并将x+1后赋值给创建的同名变量x,不可变元素类型中,两者没有区别
//英文字母大小写的ASCII码值刚好只有第六位不同,通过异或一个32刚好互相转化,而神奇的是,空格的ASCII码值刚好是32,所以直接与空格异或就可以转换大小写
//a = 01100001 A = 01000001
arr[pos] ^= ' ';
dfs(arr, pos + 1, res);
}
}
复杂度分析
- 时间复杂度:O(n×2^n),其中 n 为字符串的长度。递归深度最多为 n,所有可能的递归子状态最多为 2^n个,每个子状态的搜索时间为 O(n),因此时间复杂度为O(n×2n)。
- 空间复杂度:O(n×2^n),list集合中右2^n个序列,每个序列所需要的空间为O(n),因此空间复杂度为O(n×2^n)