找到达到多个级别的方法

Posted

技术标签:

【中文标题】找到达到多个级别的方法【英文标题】:Find ways to get to a number of levels 【发布时间】:2020-07-30 17:36:05 【问题描述】:

我在 CoderByte 上遇到了这个问题。要求是找到多种方法。我在 *** 和其他网站上找到了解决方案。但是继续前进,我还需要所有可能的方法来达到第 N 步。

问题描述:有N个台阶的楼梯,一次可以爬1或2个台阶。您需要计算并返回爬楼梯的独特方式的总数。采取的步骤顺序很重要。

例如,

输入:N = 3

输出:3

说明:爬 3 级楼梯有 3 种独特的方式:1,1,1、2,1 和 1,2

注意:在另一种情况下,一个人一次可以采取 2 或 3 或 4 个步骤(我知道这实际上是不可能的,但尝试为代码中的输入步骤添加可伸缩性)

我无法找到正确的逻辑来获得所有可能的方法。如果我在 Python 中获得解决方案会很有用,但这并不是严格的要求。

【问题讨论】:

【参考方案1】:

这是使用itertools 库的最小解决方案:

from itertools import permutations, chain

solve = lambda n: [(1,)*n] + list(set(chain(*[permutations((2,)*i + (1,)*(n-2*i)) for i in range(1, n//2+1)])))

对于您的示例输入:

> solve(3)
[(1, 1, 1), (1, 2), (2, 1)]

它是如何工作的?

如果我们向后退一步,就会更容易看到正在发生的事情:

def solve(n):
    combinations = [(1,)*n]
    for i in range(1, n//2+1):
        combinations.extend(permutations((2,)*i + (1,)*(n-2*i)))
    return list(set(combinations))

最微不足道的情况是您一次迈出一步,所以 n 步骤:(1,)*n。然后我们可以看看我们最多可以走多少双步,这是 n 除以 2 的底数:n//2。然后我们迭代可能的双步:尝试在每次迭代(2,)*i 时添加一个双步,用单步填充剩余空间(1,)*(n-2*i)

来自 itertools 的函数 permutations 将为该迭代生成所有可能的单步和双步排列。输入 (1,1,2),它将生成 (1,1,2)、(1,2,1) 和 (2,1,1)。最后,我们使用将结果转换为set 的技巧来删除重复项,然后将其转换回列表。


任何数量和长度的步骤的泛化(不是最优的!)

一个班轮:

from itertools import permutations, chain, combinations_with_replacement

solve = lambda n, steps: list(set(chain(*[permutations(sequence) for sequence in chain(*[combinations_with_replacement(steps, r) for r in range(n//min(steps)+1)]) if sum(sequence) == n])))

示例输出:

> solve(8, [2,3])
[(3, 2, 3), (2, 3, 3), (2, 2, 2, 2), (3, 3, 2)]

更易于阅读的版本:

def solve(n, steps):
    result = []
    for sequence_length in range(n//min(steps)+1):
        sequences = combinations_with_replacement(steps, sequence_length)
        for sequence in sequences:
            if sum(sequence) == n:
                result.extend(permutations(sequence))
    return list(set(result))

【讨论】:

谢谢,@stjernaluiht。这是一个简化的解决方案,效果很好。我想知道如果用例更改为一次爬 2 或 3 步而不是 1 或 2 步会怎样。然后,当 n 是代码中的奇数时,一次 2 步的默认情况可能不起作用。请分享您的想法。 很高兴它对你有用!这个问题对于任意步数的推广实际上是一个NP-hard问题,具体来说是subset sum problem的一个变体。这意味着直到找到解决方案的时间随着输入的大小呈指数增长。 我在答案中添加了适用于任意数量和长度的步骤的概括,但这远非最佳解决方案。 是的,这适用于所有输入案例。谢谢你快速的回复。真的很感激。【参考方案2】:
def solve(n) :
    if (n == 0):
        return [[]]
    else:
        left_results = []
        right_results = []

        if (n > 0):
            left_results = solve(n - 1)
            for res in left_results: # Add the current step to every result
                res.append(1)

        if (n > 1):
            right_results = solve(n - 2)
            for res in right_results: # Same above
                res.append(2)

        return left_results + right_results

我认为使用动态编程有更好的方法来做到这一点,但我不知道该怎么做。无论如何,希望它有所帮助。

【讨论】:

以上是关于找到达到多个级别的方法的主要内容,如果未能解决你的问题,请参考以下文章

Android API 级别 16 及更高级别的 Torch 应用程序

无线同步技术

文件读写

withCount() 用于多个级别?

Python-Sphinx中Toctree的多个级别

R:根据OR条件创建具有多个级别的新变量[重复]