找到达到多个级别的方法
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
我认为使用动态编程有更好的方法来做到这一点,但我不知道该怎么做。无论如何,希望它有所帮助。
【讨论】:
以上是关于找到达到多个级别的方法的主要内容,如果未能解决你的问题,请参考以下文章