Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string.  Return a list of all possible strings we could create.

  1. Examples:
  2. Input: S = "a1b2"
  3. Output: ["a1b2", "a1B2", "A1b2", "A1B2"]
  4.  
  5. Input: S = "3z4"
  6. Output: ["3z4", "3Z4"]
  7.  
  8. Input: S = "12345"
  9. Output: ["12345"]

Note:

  • S will be a string with length at most 12.
  • S will consist only of letters or digits.

这道题给了我们一个只包含字母和数字的字符串,让我们将字母以大小写进行全排列,给的例子很好的说明了题意。博主认为这道题给Easy有点不合适,至少应该是Medium的水准。这题主要参考了官方解答贴的解法,我们关心的是字母,数字的处理很简单,直接加上就可以了。比如说S = "abc",那么先让 res = [""],然后res中的每个字符串分别加上第一个字符a和A,得到 ["a", "A"],然后res中的每个字符串分别加上第二个字符b和B,得到 ["ab", "Ab", "aB", "AB"],然后res中的每个字符串分别加上第三个字符c和C,得到 ["abc", "Abc", "aBc", "ABc", "abC", "AbC", "aBC", "ABC"],参见代码如下:

解法一:

  1. class Solution {
  2. public:
  3. vector<string> letterCasePermutation(string S) {
  4. vector<string> res{""};
  5. for (char c : S) {
  6. int len = res.size();
  7. if (c >= '' && c <= '') {
  8. for (string &str : res) str.push_back(c);
  9. } else {
  10. for (int i = ; i < len; ++i) {
  11. res.push_back(res[i]);
  12. res[i].push_back(tolower(c));
  13. res[len + i].push_back(toupper(c));
  14. }
  15. }
  16. }
  17. return res;
  18. }
  19. };

下面这种解法跟上面的解法没有太大的区别,只不过没有用到tolower()和toupper()这两个built-in函数,而是使用了一个trick来flip大小写字母,通过亦或32实现,为什么呢?因为我们知道 'A' = 65, 'B' = 66, 和 'a' = 97, 'b' = 98, 小写字母的ASCII码比大写字母多32,刚好是(1 << 5),那么我们只要flip第五位上的1,就可以实现大小写的交替了,参见代码如下:

解法二:

  1. class Solution {
  2. public:
  3. vector<string> letterCasePermutation(string S) {
  4. vector<string> res{""};
  5. for (char c : S) {
  6. int len = res.size();
  7. if (c >= '' && c <= '') {
  8. for (string &str : res) str.push_back(c);
  9. } else {
  10. for (int i = ; i < len; ++i) {
  11. res.push_back(res[i]);
  12. res[i].push_back(c);
  13. res[len + i].push_back(c ^ );
  14. }
  15. }
  16. }
  17. return res;
  18. }
  19. };

我们再来看一种递归的写法,是一种回溯的思路,比如说S = "abc",用一个pos指向当前处理的位置,初始化带入0,然后再递归函数中,如果pos等于s的长度了,那么将s存入结果res再返回;否则调用递归函数,此时带入pos+1,那么递归函数就会一直深入,直到pos等于s的长度了,那么此时就把"abc"存入结果res了,返回后此时pos=2,发现s[pos]是字母,则用上面解法中的flip方法来翻转字母,并且调用递归函数,这样"abC"就会存入结果res中,然后回溯到pos=1的位置,s[pos]是字符,可以flip,并且调用递归函数,这样"aBC"就会存入结果res中,然后pos继续往后遍历,这样"aBc"就会存入结果res中,然后回溯到pos=0的位置,s[pos]是字符,可以flip,并且调用递归函数,这样"ABc"就会存入结果res中,然后继续回溯,这样"ABC"就会存入结果res中,pos又回溯到1的位置,s[pos]是字符,可以flip,并且调用递归函数,这样"AbC"就会存入结果res中,然后pos继续往后遍历,这样"Abc"就会存入结果res中,整个的顺序为:[abc abC aBC aBc ABc ABC AbC Abc],参见代码如下:

解法三:

  1. class Solution {
  2. public:
  3. vector<string> letterCasePermutation(string S) {
  4. vector<string> res;
  5. helper(S, , res);
  6. return res;
  7. }
  8. void helper(string& s, int pos, vector<string>& res) {
  9. if (pos == s.size()) {
  10. res.push_back(s);
  11. return;
  12. }
  13. helper(s, pos + , res);
  14. if (s[pos] > '') {
  15. s[pos] ^= ;
  16. helper(s, pos + , res);
  17. }
  18. }
  19. };

下面这种解法是官方解答贴的Binary Mask解法,感觉也很巧妙,如果我们仔细观察S = "abc"这个例子,结果会返回8个,为什么是8个呢,因为每个字母都有大小写两种可能,那么三个字母就有2x2x2=8,正好是2的三次方,那么不正好和二进制数相对应么,如果1对应大写字母,0对应小写字母,则有:

  1. -> ABC
  2. -> ABc
  3. -> AbC
  4. -> Abc
  5. -> aBC
  6. -> aBc
  7. -> abC
  8. -> abc

这样的话,我们只需要先统计出S中字母的个数cnt,然后遍历 [0, 2^cnt) 中的每个数字,对于每个数字,再遍历S中的每个字符,如果是字母,那么如果当前位是1,则加入小写字母,反之加入大写字母;如果是数字,则直接加入即可。我们用j指向位,每次处理完一位后j自增1,表示对下一位进行处理,参见代码如下:

解法四:

  1. class Solution {
  2. public:
  3. vector<string> letterCasePermutation(string S) {
  4. vector<string> res;
  5. int cnt = ;
  6. for (char c : S) {
  7. if (c > '') ++cnt;
  8. }
  9. for (int i = ; i < ( << cnt); ++i) {
  10. int j = ;
  11. string word = "";
  12. for (char c : S) {
  13. if (c > '') {
  14. if (((i >> j++) & ) == ) {
  15. word.push_back(tolower(c));
  16. } else {
  17. word.push_back(toupper(c));
  18. }
  19. } else {
  20. word.push_back(c);
  21. }
  22. }
  23. res.push_back(word);
  24. }
  25. return res;
  26. }
  27. };

类似题目:

Subsets

参考资料:

https://leetcode.com/problems/letter-case-permutation/solution/

https://leetcode.com/problems/letter-case-permutation/discuss/115515/C++-backtrack-solution-w-trick

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Letter Case Permutation 字母大小写全排列的更多相关文章

  1. Leetcode784.Letter Case Permutation字母大小写全排列

    给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串.返回所有可能得到的字符串集合. 示例: 输入: S = "a1b2" 输出: ["a1 ...

  2. Java实现 LeetCode 784 字母大小写全排列(DFS)

    784. 字母大小写全排列 给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串.返回所有可能得到的字符串集合. 示例: 输入: S = "a1b2" ...

  3. 【Leetcode_easy】784. Letter Case Permutation

    problem 784. Letter Case Permutation 参考 1. Leetcode_easy_784. Letter Case Permutation; 2. Grandyang; ...

  4. [LeetCode] 784. 字母大小写全排列 ☆☆☆(回溯、深度优先遍历)

    https://leetcode-cn.com/problems/letter-case-permutation/solution/shen-du-you-xian-bian-li-hui-su-su ...

  5. 784. Letter Case Permutation

    这个题的思想很重要,两种方法 第一种,回溯法 class Solution { public: int sz; vector<string> letterCasePermutation(s ...

  6. [Swift]LeetCode784. 字母大小写全排列 | Letter Case Permutation

    Given a string S, we can transform every letter individually to be lowercase or uppercase to create ...

  7. 784. Letter Case Permutation C++字母大小写全排列

    网址:https://leetcode.com/problems/letter-case-permutation/ basic backtracking class Solution { public ...

  8. 784. Letter Case Permutation 字符串中字母的大小写组合

    [抄题]: Given a string S, we can transform every letter individually to be lowercase or uppercase to c ...

  9. 【LeetCode】784. Letter Case Permutation 解题报告 (Python&C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 回溯法 循环 日期 题目地址:https://leet ...

随机推荐

  1. 【原创】支持同时生成多个main函数 makefile 模板

    背景: 去年做项目的时候,由于有需要编译出多个可执行文件的需求,修改了Makefile使其支持生成多个结果(编译多个含有main函数的文件),但总觉得自己的实现不够完美. 今年又遇到这样需求的时候,可 ...

  2. 第十七节: EF的CodeFirst模式的四种初始化策略和通过Migration进行数据的迁移

    一. 四种初始化策略 EF的CodeFirst模式下数据库的初始化有四种策略: 1. CreateDatabaseIfNotExists:EF的默认策略,数据库不存在,生成数据库:一旦model发生变 ...

  3. PHP中的常用数组操作方法

    一.数组操作的基本函数 数组的键名和值array_values($arr);  获得数组的值array_keys($arr);  获得数组的键名array_flip($arr);  数组中的值与键名互 ...

  4. IDEA远程调试服务器代码

    先在idea添加一个remote,host填服务器ip,port填监听服务器端口,默认5005 然后在服务器tomcat catalina.sh 添加(红色部分): JAVA_OPTS="$ ...

  5. Redis中bitmap的妙用

    BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间. Redis中的 ...

  6. Penettation testing with the bush Shell

    1.  Network Reconnaissance first we can use the command to gather the site information by whois eg : ...

  7. spring-boot-starter-thymeleaf 避坑指南

    第一步:pom配置环境 先不要管包是做什么的 总之必须要有 否则进坑 <!--避坑包--> <dependency> <groupId>net.sourceforg ...

  8. 分享一个学习的网站:每天会有大量AI相关的干货(论文分享,行业动态,相关竞赛经验分享等)http://www.deepsmart.ai/

    网址:http://www.deepsmart.ai/ 微信公众号如下:

  9. drop、truncate和delete的区别

    TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行.但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源 ...

  10. Dapper结合Repository模式的应用

    Dapper结合Repository模式的应用,包括如何在数据访问层(DAL)使用Dapper组件. Dapper在真实项目中使用,扩展IDbConnection的功能,支持Oracle.MS SQL ...