【LeetCode】字母大小写全排列Java题解

98 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情

题目描述

给定一个字符串 s ,通过将字符串 s 中的每个字母转变大小写,我们可以获得一个新的字符串。

返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。

示例 1:

输入:s = "a1b2"
输出:["a1b2", "a1B2", "A1b2", "A1B2"]

示例 2:

输入: s = "3z4"
输出: ["3z4","3Z4"]

思路分析

  • 今天的算法题目字符串类型题目。题目比较清晰,我们可以拆分成两个子问题。一是全排列的问题。二是大小写字母转化的问题。具体到这个问题,频繁修改字符串,我们使用StringBuilder类减少无用对象的创建和使用,提升效率。初始化StringBuilder,然后逐个遍历s的字符,判断是否是字母。如果是大写就转换成小写,然后是小写就转换成大写。当StringBuilder长度与s长度相等时,就是其中一个答案。
  • 对于大小写字母转化的问题,这里主要是使用 ASCII 码的知识,其中 'A' 的ASCII的十进制是97,'a' 的ASCII的十进制是65,中间差值是32。利用这一性质,我们就可以实现字符的大小写转化,但是写的稍微有一点冗余。我学习官方题解,可以(char) (s.charAt(pos) ^ 32)这个这样完成大小写转化。为什么呢?比如 A 的ASCII 二进制为 01000010,32的二进制值为 00100000,异或之后,就可以完成转换。
  • 具体实现代码如下,供参考。

通过代码

class Solution {
    public List<String> letterCasePermutation(String s) {
        List<String> ans = new ArrayList<String>();
        Queue<StringBuilder> queue = new ArrayDeque<StringBuilder>();
        queue.offer(new StringBuilder());
        while (!queue.isEmpty()) {
            StringBuilder curr = queue.peek();
            if (curr.length() == s.length()) {
                ans.add(curr.toString());
                queue.poll();
            } else {
                int pos = curr.length();
                if (Character.isLetter(s.charAt(pos))) {
                    StringBuilder next = new StringBuilder(curr);
                    next.append((char) (s.charAt(pos) ^ 32));
                    queue.offer(next);
                }
                curr.append(s.charAt(pos));
            }
        }
        return ans;
    }
}

总结

  • 今天的题目比较有难度,可以多练习几次。上述算法的时间复杂度是O(2的 n次方),空间复杂度是O(n × 2的 n次方 )
  • 坚持算法每日一题,加油!我会继续更新,也欢迎算法爱好者一起交流学习。