字母大小写全排列

171 阅读1分钟

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

784. 字母大小写全排列

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

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

 

示例 1:

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

示例 2:

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

 

提示:

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

方法一:直接递归

这道题的官解用了三种方法,涉及广度优先搜索、深度优先搜索(回溯)这些核武器。

但是本题可以不管这些高大上的概念,直接进行最朴素的递归。

解题步骤

● 用递归模拟出所有情况
● 遇到非字母元素,就回溯
● 收集所有到达递归终点的情况,并返回

/**
 * @param {string} s
 * @return {string[]}
 */
function letterCasePermutation(s) {
  const res: string[] = [];
  const dfs = (path: string, level: number) => {
    while(!/[a-zA-z]/.test(s[level])) {
      path += s[level++];
    }
    if(path.length === s.length) { // 结束当前递归的条件
      res.push(path);
      return;
    }
    dfs(path + s[level].toLocaleLowerCase(), level + 1);
    dfs(path + s[level].toLocaleUpperCase(), level + 1);
  }
  dfs('', 0);
  return res;
}

方法二:迭代

  • 实际每增加一个字母,结果数量 * 2,例如 'a' => ['a', 'A'], 'ab' => {'ab', 'AB', 'Ab', 'aB'}
  • 观察 'ab' 的逐位增加规律 ['a', 'A'] -> ['a + b', 'a + B', 'A + b', 'A + B']
  • 观察 'abc' 的逐位增加规律 ['a', 'A'] -> ['a + b', 'a + B', 'A + b', 'A + B'] => ['a + b + c', 'a + b + C', 'a + B + c', 'a + B + C', 'A + b + c', 'A + b + C', 'A + B + c' + 'A + B + C']
  • 以此类推,观察上面的规律,感觉就很类似二叉树。
  • 那么问题就可以变成:遍历二叉树所有可能性,遇到字母复制之前的全部节点,然后拼接大小写即可,非字母直接原样拼接,最终就是我们期望的结果
/**
 * @param {string} s
 * @return {string[]}
 */
var letterCasePermutation = function (s) {
  s = s.toLowerCase()
  let arr = [s[0]];
  if (s[0].charCodeAt() > 96) arr.push(s[0].toUpperCase())
  for (let i = 1; i < s.length; i++) {
    arr = arr.map(word => word += s[i])
    if (s[i].charCodeAt() > 96) arr = arr.concat(arr.map(word => word.slice(0, -1) + s[i].toUpperCase()))
  }
  return arr
};