题目相关
题目链接
LeetCode中国,https://leetcode-cn.com/problems/letter-case-permutation/。注意需要登录。
我的OJ,http://47.110.135.197/problem.php?id=5257。
题目描述
给定一个字符串 S,通过将字符串 S 中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。
输入格式
只有一行,一个字符串 S。
保证所有的输入只有数字和字母。
输出格式
若干行,每行一个字符串,表示 S 的一个变化。
输入样例
a1b2
输出样例
["a1b2","a1B2","A1b2","A1B2"]
题目分析
题意分析
给定字符串 s,按照规则输出所有变化。规则有两条:1、字母保持不变;2、字母改变大小写。一个标准的模板 DFS 题,难度入门级。
样例数据分析
拿到字符串 s 后,从第 0 个字符开始逐一搜索。假设该位置字母为 a,哪么根据规则,我们可以绘制出如下图所示的变化可能:
方案一,向左边走,保持字母不变,然后继续搜索下一个字符。我们可以发现,保持不变,不管是数字还是字母操作是一样的。
方案二,向右走,如果是字母,则将其大小写变化,然后继续搜索下一个字符。
整个 DFS 过程中,我们先使用方案一,再使用方案二。下面我们用输入样例 a1b2,来绘模拟一下 DFS 遍历过程,可以绘制出入下图所示的变化过程,红色为输出。
算法思路
1、读入字符串 s。
2、从第零个字符出发,按照规则(先使用方案一,再使用方案二)变化。
搜索终止条件
终止条件必然是搜索到了字符串的长度。
搜索函数参数
下面我们来分析 dfs() 函数需要哪些参数。由于得到的结果是字符串,因此 dfs() 函数中,
1、需要传入一个字符串,表示当前的字符是怎么样的。
2、还需要一个位置,表示当前枚举到字符串的哪个地方,即字符串的第几位。
所以我们可以确定本题的 dfs() 函数原型应该是如下所示:
//参数s:表示当前字符串的内容
//参数index:表示现在枚举到字符串s的第几位
void dfs(string &s, int index) {
if (index==s.length()) {
return;
}
dfs(s, index+1);//保持不变直接搜索下一位
if (s[index]>='A') {
//是字母
s[index] ^= 32;//大小写切换
dfs(s, index+1);//搜索下一位
}
}
开始调用方式
dfs(s, 0);//表示从第0位开始搜索字符串s
回溯
本题不需要回溯,直接搜索就可以了。
AC 参考代码
class Solution {
public:
vector<string> ans;
vector<string> letterCasePermutation(string S) {
dfs(S, 0);
return ans;
}
void dfs(string &s, int idx) {
if (s.length()==idx) {
ans.push_back(s);
return;
}
//本位不变,搜索下一位
dfs(s, idx+1);
//本位变,搜索下一位
if (s[idx]>='A') {
s[idx] ^= 32;
dfs(s, idx+1);
}
}
};
代码导读
大小写字母变化
大小写字母变化,可以使用判断语句直接判断。这里我使用了一个小技巧,当前字母异或 32。使用了位操作。下面我们来分析一下为什么可以做到。字符 'A' 对应的 ASCII 是 65,对应的二进制为 0b01000001,而字符 'a' 对应的 ASCII 是 97,对应的二进制为 0b01100001,对比一下 'A‘ 和 'a’ 的二级制值,我们可以发现差异为一位(红色表示),即 0b00100000,对应的十进制为 32。'B' 和 'b' 也是这样,其他以此类推。
DFS 代码套路
DFS 代码套路可以参考我的另外一个文章,https://blog.csdn.net/justidle/article/details/104925699。