【问题标题】:Array searching and slicing数组搜索和切片
【发布时间】:2022-01-14 22:10:02
【问题描述】:

鉴于字符串 nums 仅包含数字和数字数组 predefinedNumbers,我必须基于 nums 构造一个新字符串,但冒号之间的每个数字必须是来自预定义数字和返回所有可能性。

示例输入:

nums = "143163421154143"
predefinedNumbers = ["21154", "143", "21154143", "1634", "163421154"]

期望的输出:

[ ":143:1634:21154:143:", ":143:163421154:143:", ":143:1634:21154143:" ]

到目前为止,我尝试了这段代码,但这不是我需要的结果,我一直在试图理解如何递归地检查它:

let nums = "143163421154143";
predefinedNumbers = ["21154", "143", "21154143", "1634", "163421154"];


let newArray=[];
function makeNumSentences (nums, predefinedNumbers) {
    predefinedNumbers.map(item => {
        if (nums.includes(item)) {
            newArray.push(item)
        }
    })
    
    console.log(newArray.join(':'));
        };
        
        
makeNumSentences("143163421154143",["21154", "143", "21154143", "1634", "163421154"])

非常感谢任何提示。

【问题讨论】:

    标签: javascript algorithm permutation


    【解决方案1】:

    首先,请阅读How do I ask and answer homework questions?

    不过,既然已经有一个公认的答案,我将只展示一种替代技术。元素是数字的事实是没有意义的。同样的技术适用于任何字符串。 (有数学技术可以找到正确的值,但它们会很快溢出正常数字,并且由于输出无论如何都需要是字符串,似乎没有必要追求它们。)

    递归地考虑这个,我们可以把它分成两部分。我的哪些预定义值出现在目标字符串的开头?对于其中的每一个,我如何对字符串的其余部分执行相同的操作?递归需要一个基本情况,我们可以说如果目标字符串为空,那么我们可以返回一个空字符串。

    我们可以这样实现:

    const make = (target, sources) =>
      target .length == 0
        ? [[]]
        : sources .filter (s => target .startsWith (s)) 
                  .flatMap (s => make (target .slice (s .length), sources) .map (r => [s, ...r]))
    
    const makeNumSentences = (target, parts) => 
      make (target, parts) .map (r => `:${r.join(':')}:`)
    
    
    const nums = "143163421154143"
    const predefinedNumbers = ["21154", "143", "21154143", "1634", "163421154"]
    
    console .log (makeNumSentences (nums, predefinedNumbers))

    请注意分解成一个主递归函数,它从我们的源 ([["143", "1634", "21154", "143"], ["143", "1634", "21154143"], ["143", "163421154", "143"]]) 返回一个元素数组的数组,以及一个将它们组合成输出格式的包装器。 ([":143:1634:21154:143:", ":143:1634:21154143:", ":143:163421154:143:"])。在我看来,这是对工作的正确分解。数组很好用,我们可以用它们做更多的事情。但这不是唯一的方法。我们可以改变它直接返回字符串:

    const make = (target, sources) =>
      target .length == 0
        ? ['']
        : sources 
           .filter (s => target .startsWith (s)) 
           .flatMap (s => make (target .slice (s .length), sources) .map (r => `:${s}${r}` +  (r ? '' : ':')))
    
    const nums = "143163421154143"
    const predefinedNumbers = ["21154", "143", "21154143", "1634", "163421154"]
    
    console .log (make (nums, predefinedNumbers))

    请注意,这里在构建字符串时有一些额外的复杂性。这是因为尾随“:”。我们只想在现有字符串为空时的第一步添加它。 (我们总是添加前导。)

    【讨论】:

      【解决方案2】:

      请注意,如果nums 不是仅由predefinedNumbers 组成,则循环将永远不会结束。

      const nums = "143163421154143";
      const predefinedNumbers = ["21154", "143", "21154143", "1634", "163421154"];
      const result = [];
      
      function makeNumSentences(nums) {
        check([], nums);
        console.log(result);
      };
      
      function check(array, nums) {
        predefinedNumbers.forEach(e => {
          if (nums.startsWith(e)) {
            const newArray = array.concat(e);
            const newNums = nums.slice(e.length);
            if (newNums) { check(newArray, newNums); }
            else { result.push(newArray.join(':')); }
          }
        });
      }
              
              
      makeNumSentences(nums);

      【讨论】:

        猜你喜欢
        • 2018-05-27
        • 2012-11-10
        • 2021-05-30
        • 1970-01-01
        • 2022-07-21
        • 2014-05-07
        • 2015-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多