【2022-10-30每日一题】784. 字母大小写全排列[Medium]

2022-10-30
2分钟阅读时长

2022-10-30每日一题:784. 字母大小写全排列

难度:Medium

标签:位运算 、 字符串 、 回溯

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

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

 

示例 1:

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

示例 2:

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

 

提示:

  • 1 <= s.length <= 12
  • s 由小写英文字母、大写英文字母和数字组成

方法一:回溯

个人写法

func letterCasePermutation(s string) (ans []string) {
    n := len(s)
    sb := []byte(s)
    var dfs func (i int)
    dfs = func(i int) {
        if i == n {
            ans = append(ans, string(sb))
            return
        }
        dfs(i+1)
        if sb[i] < '0' || sb[i] > '9' {
            sb[i] ^= 32
            dfs(i+1)
            sb[i] ^= 32
        }
    }
    dfs(0)
    return ans
}

官方优化

func letterCasePermutation(s string) (ans []string) {
    n, sb := len(s), []byte(s)
    var dfs func (i int)
    dfs = func(i int) {
        // 跳过数字
        for i < n && unicode.IsDigit(rune(sb[i])) {
            i++
        }
        if i == n {
            ans = append(ans, string(sb))
            return
        }
        dfs(i+1)
        sb[i] ^= 32 // 大小写转换
        dfs(i+1)
        sb[i] ^= 32 // 恢复
    }
    dfs(0)
    return ans
}

复杂度分析

  • 时间复杂度:O(n×2^n)。
  • 空间复杂度:O(n×2^n)。

方法二:广度优先遍历

func letterCasePermutation(s string) (ans []string) {
    q, n := []string{""}, len(s)
    for len(q) > 0 {
        cur := q[0]
        pos := len(cur)
        if pos == n {
            ans = append(ans, cur)
            q = q[1:]
        } else {
            if unicode.IsLetter(rune(s[pos])) { // 字母出来
                q = append(q, cur + string(s[pos]^32))
            }
            q[0] += string(s[pos]) // 原地修改
        }
    }
    return ans
}

复杂度分析

  • 时间复杂度:O(n×2^n)。
  • 空间复杂度:O(n×2^n)。

方法三:二进制位图

func letterCasePermutation(s string) (ans []string) {
    // 统计字母个数
    m := 0
    for _, c := range s {
        if unicode.IsLetter(c) {
            m++
        }
    }
    for mask := 0; mask < 1<<m; mask++ {
        t, k := []rune(s), 0
        for i, c := range t {
            if unicode.IsLetter(c) {
                if mask>>k&1 == 1 {
                    t[i] = unicode.ToUpper(c) // 第k位为1,转大写
                } else {
                    t[i] = unicode.ToLower(c) // 第k位为0,转小写
                }
                k++
            }
        }
        ans = append(ans, string(t))
    }
    return ans
}

复杂度分析

  • 时间复杂度:O(n×2^n)。
  • 空间复杂度:O(n×2^n)。

LeetCode题库地址