【问题标题】:Varying number of related nested for loops不同数量的相关嵌套 for 循环
【发布时间】:2018-06-10 19:32:27
【问题描述】:

我正在尝试从滚动 n 个骰子中确定所有可能的总和,其中 n 在编译时是未知的。

对于两个骰子,解决方案很简单,只需遍历两个骰子并将每个可能的面相加即可。如果传入 2 个 6 面骰子,排序结果将是:[2,3,3,4,4,4,5,5,5,5,6,6,6,6,6,7,7, 7,7,7,7,8,8,8,8,8,9,9,9,9,10,10,10,11,11,12]

我尝试将此解决方案扩展到任何 n 个骰子,但我意识到我需要 n 个 for 循环。

for(let i = 0; i < numDice; i++)
{
    dice.push(sides); 
}

for(let i = 0; i < numSides; i++)
{
    for(let j = 1; j < dice.length; j++)
    {
        for(let k = 0; k < numSides; k++)
        {
            results.add(dice[0][i] + dice[j][k]);
        }
    }
}

我还尝试了一种基于递归的方法,如下面的第一个问题所建议的那样。我相信它会循环正确的次数,但我不知道如何在不引入更多循环的情况下定义我的求和函数。

function doCallMany(numDice, numSides, sumFunc)
{
    if(numDice == 0) 
    {
        sumfunc(numDice, numSides) //?
    }
    else
    {
        for(let i = 0; i < numSides; i++)
        {
            doCallMany(numDice--, numSides, sumFunc)
        }
    }
}

我查看了herehere 的类似问题,但他们没有回答我的问题。第一个不是因为我需要在循环中执行的操作不是独立的。第二个很接近,但答案依赖于 Python 特定的答案。

【问题讨论】:

  • 任何中等大小的输入都会有巨大的时间复杂度。您可以考虑使用数学算法来确定这一点,而不是蛮力

标签: javascript algorithm nested-loops


【解决方案1】:

关于解决方案复杂性的评论是正确的。它很快变大。话虽如此,为了解决您最初的问题,您可以使用一个相当简单的递归函数来处理少量输入。基本上你从一个骰子数组开始,弹出一个将它加到一个总和中,然后用这个总和和数组的其余部分递归。

例如:

function sums(dice, sum = 0, ans = []) {
  if (dice.length === 0) ans.push(sum) // edge case, no more dice
  else {
    let d = dice[0]
    for (let i = 1; i <= d; i++) {
      sums(dice.slice(1), sum + i, ans) // recurse with remaining dice
    }
    return ans
  }
}

// two six-sided dice
let ans = sums([6, 6]) 
console.log(JSON.stringify(ans.sort((a, b) => a - b)))

// three three-sided dice
ans = sums([3, 3, 3]) 
console.log(JSON.stringify(ans.sort((a, b) => a - b)))

【讨论】:

  • 不错的解决方案! [3,4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,17,17,17,18]
【解决方案2】:

我建议你使用回溯法。 它使您可以改变要执行的循环数。您甚至可以执行随机数量的循环,因为循环的数量可以保存在一个变量中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    相关资源
    最近更新 更多