【问题标题】:Issue with recursion while Permutations of a String字符串排列时的递归问题
【发布时间】:2019-09-05 20:37:51
【问题描述】:

我正在尝试生成字符串的所有大写排列。

例如:

capitalPermutations(word) - 给定一串字母,返回所有 该单词的大小写字母的可能组合。

示例:'abc'

输出:['abc' 'Abc' 'aBc' 'ABc' 'abC' 'AbC' 'aBC' 'ABC']

以迭代和递归的方式实现这一点。

这是我的尝试:

function capitalPermutations(word) {
  const res = new Set();
  
  // Push the actual word first.
  res.add(word);
  
  helper(word, res, '');
  
  return res;
  
  function helper(word, res, str='') {
    
    if(str.length === word.length) return;
    
    const len = word.length;
    res.add(word);
    
    // Capitalization
    for(let i=0; i< word.length; i++) {
      const substr = word.substring(0, i+1); // a, ab, abc
      str += substr; // str === "ABC" | len = 3
      const upper = str.toUpperCase(); // A, AB, ABC
      const remaining = `${upper}${word.substring(i, len)}`; // Abc , ABc, 
      helper(remaining, res, str);
    }
  }

}
var testWord1 = "abc"
console.log(capitalPermutations(testWord1))

问题: 它进入无限递归。即使我有一个破碎的条件。如果有人能纠正我的错误之处,我将不胜感激。

【问题讨论】:

  • @kmgt 这没有什么问题,这就是递归的真正好处——迭代不容易实现。
  • 作业令人困惑。这实际上与排列无关,排列是关于排序的。
  • "如果有人能纠正我的错误之处,我将不胜感激" - 你能试着解释一下你要去哪里吗?我完全不明白你的方法。为什么要遍历单词长度并从中获取所有前缀?你为什么要str += substr?在您的基本情况下,您的意思是与原始的 words 长度(传递给 capitalPermutations 的长度)或递归调用中传递的 word 进行比较?为什么在每个递归步骤中都将word 添加到result,而不是最后一次?
  • @Bergi 感谢您的评论。我使用str 来跟踪我正在处理的字符串数量。我知道我的代码令人困惑(只是想学习!)感谢您的帮助和所有 cmets。在我的基本情况下,我希望将我的原始字长(而不是通过的字长)进行比较我的错!
  • 不会生成所有排列生成字符串,例如cabbac 等?这个任务不只是关于生成所有不同的套管变体吗?

标签: javascript recursion


【解决方案1】:

像二叉树一样遍历字符串

const permute = (str, prefix='') => {
  const idx = prefix.length
  if (idx===str.length)
    return [prefix]

  const lower = str[idx].toLowerCase()
  const upper = str[idx].toUpperCase()

  return [...permute(str, prefix + lower), ...permute(str, prefix + upper)]
}

console.log(permute('abc'))

【讨论】:

    【解决方案2】:

    您可以采用递归函数,该函数获取上次访问索引的收集字母,并检查收集的字母字符串是否与给定字符串的长度相同。然后将字符串推送到结果集。

    关键是一个小写字母和一个大写字母的递归的双重调用。

    function capitalPermutations(word) {
        function iter(temp = '') {
            if (temp.length === word.length) {
                result.push(temp);
                return;
            }
            iter(temp + word[temp.length].toLowerCase());
            iter(temp + word[temp.length].toUpperCase());
        }
    
        var result = [];
        iter();
        return result;
    }
    
    console.log(capitalPermutations('abc'));

    迭代方法也是如此

    function capitalPermutations(word) {
        var result = [''],
            temp,
            i, j, upper, lower;
    
        for (i = 0; i < word.length; i++) {
            temp = result;
            result = [];
            lower = word[i].toLowerCase();
            upper = word[i].toUpperCase();
            for (j = 0; j < temp.length; j++) {
                result.push(temp[j] + lower, temp[j] + upper);
            }
        }
        return result;
    }
    
    console.log(capitalPermutations('abc'));

    【讨论】:

    • 谢谢。好干净!如果我要迭代地这样做,我会怎么做?我正在考虑有两个 for 循环并在其中一个循环中执行子字符串?
    • 这也适用于“abcde”,所以它似乎是一个很好的解决方案。
    • ^^ 这就是我这么爱的原因!
    • @TechnoCorner。对于迭代方法,您需要两个循环,一个用于单词的字符,一个用于部分结果。请参阅编辑。
    • @customcommander 这是一个错字……让我来解决这个问题。这是正确的答案
    【解决方案3】:

    这是一个带有 flatMap 的:

    function f(str){
      return str ? f(str.slice(1)).flatMap(sfx =>
        [str[0].toLowerCase() + sfx, str[0].toUpperCase() + sfx]) : [""]
    }
    
    console.log(JSON.stringify(f("abc")))

    【讨论】:

      【解决方案4】:

      迭代:

      function f(str){
        let res = [""]
        for (let c of str)
          res = res.flatMap(pfx =>
            [pfx + c.toUpperCase(), pfx + c.toLowerCase()])
        return res
      }
      
      console.log(JSON.stringify(f("abc")))

      【讨论】:

        猜你喜欢
        • 2023-04-11
        • 2020-03-05
        • 1970-01-01
        • 1970-01-01
        • 2012-08-24
        • 2016-04-30
        • 1970-01-01
        • 2011-11-22
        • 2014-12-03
        相关资源
        最近更新 更多