784. 字母大小写全排列

题目链接: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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值