LeetCode-Python-784. 字母大小写全排列

654 篇文章 23 订阅

给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串。返回所有可能得到的字符串集合。

示例:
输入: S = "a1b2"
输出: ["a1b2", "a1B2", "A1b2", "A1B2"]

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

输入: S = "12345"
输出: ["12345"]

注意:

  • S 的长度不超过12
  • S 仅由数字和字母组成。

第一种思路:

看到题目要求组合或者集合,马上想到可以用回溯法:回溯法本来是说对于每个元素都先考虑放它的情况,再考虑不放它的情况;放在这道题的背景里就是,对于每个字母,先考虑放它,再考虑放它的另一种大小写形式。

用dfs实现回溯,start代表目前从扫描到第几位,

如果是digit,就直接加进去,然后下一层递归

如果是alpha,就先加进去,然后下一层递归;再加对立大小写形式, 然后下一层递归。

class Solution(object):
    def letterCasePermutation(self, S):
        """
        :type S: str
        :rtype: List[str]
        """
        res = list()
        l = len(S)
        if l == 0:
            return [""]
            
        def dfs(start, temp):
            if start >= l or len(temp) == l:
                res.append(temp)
                return
            # print start, temp
            if S[start].isdigit():
                dfs(start + 1, temp + S[start])
            
            elif S[start].islower():
                dfs(start + 1, temp + S[start])
                dfs(start + 1, temp + S[start].upper())

            elif S[start].isupper():
                dfs(start + 1, temp + S[start])
                dfs(start + 1, temp + S[start].lower())
        
        dfs(0, "")
        return res

#以下是修改前
class Solution(object):
    def letterCasePermutation(self, S):
        """
        :type S: str
        :rtype: List[str]
        """
        res = list()
        l = len(S)
        if l == 0:
            return [""]
        def dfs(string, start, temp):
            if start > l or len(temp) == l:
                res.append(temp)
                return
            
            if string[start].isdigit():
                temp += string[start]
                dfs(string, start + 1, temp)
            
            if string[start].islower():
                temp += (string[start])
                dfs(string, start + 1, temp)
                temp = temp[:-1]
                temp += (string[start].upper())
                dfs(string, start + 1, temp)
            elif string[start].isupper():
                temp += string[start]
                dfs(string, start + 1, temp)
                temp = temp[:-1]
                temp += string[start].lower()
                dfs(string, start + 1, temp)
        
        dfs(S, 0, "")
        return res

第二种思路:

除了用DFS回溯实现,我们也可以用BFS来解题, 线性扫描S,

对于扫描到的每个元素, 都把它的大小写形式分别加到,目前的res里的所有结果里,这样可以得到temp,

然后用temp覆盖res。

比如对于S = "a1b2",

扫描到a时, res = [a, A]

扫描到b时, res = [a1, A1], temp = [a1b, a1B, A1b, A1B]

class Solution(object):
    def letterCasePermutation(self, S):
        """
        :type S: str
        :rtype: List[str]
        """
        import copy
        res = [""]
        
        for i, x in enumerate(S):
            if x.isdigit():
                for index, item in enumerate(res):
                    res[index] += (x)
                    
            elif x.isupper():
                temp = list()
                for index, item in enumerate(res):
                    temp.append(item + (x))
                    temp.append(item + (x.lower()))
                res = copy.deepcopy(temp[:])
                
            elif x.islower():
                temp = list()
                for index, item in enumerate(res):
                    temp.append(item + (x))
                    temp.append(item + (x.upper()))       
                res = copy.deepcopy(temp[:])
                
        return res

第三种思路:

Bitmap法,字符串S的长度为l, 则总共会有 2** l种结果,换成二进制就是0 ~ 2 **l - 1个数,

对于每个数,如果某个位上是0, 就放小写;是1, 就放大写。

class Solution(object):
    def letterCasePermutation(self, S):
        l = len(S)
        n = 2 ** l
        res = list()
        if l == 0:
            res.append("")
        for i in range(0, n):
            temp = ""

            for j in range(0, l):
                if ((2 ** j) &i) == 0:
                    temp += S[j].lower()
                else:
                    temp += S[j].upper()
            if temp not in res:
                res.append(temp)
        return res

本题跟LeetCode-Python-78. 子集的思路非常类似。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值