我在LeetCode Climbing Stairs上遇到了问题,其内容如下:
我想出了基于深度优先搜索的以下解决方案:
class Solution:
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
stack = [Node()]
ways = 0
while stack:
node = stack.pop()
if node.reached_top(n):
ways += 1
stack.extend(node.get_neighbors(n))
return ways
class Node(tuple):
def get_neighbors(self, n):
return [Node(list(self) + [steps]) for steps in (1, 2) if sum(self) + steps <= n]
def reached_top(self, n):
return sum(self) == n
因此,例如,Solution().climbStairs(2) == 2
和Solution().climbStairs(3) == 3
根据需要。问题是此解决方案超出了输入35
:
深度优先搜索似乎是解决此问题的一种相当有效的算法,但显然,它不是;关于如何改进我的解决方案的任何想法?
答案 0 :(得分:2)
最简单的方法是根据solution(n) = solution(n-1) + solution(n-2)
的事实计算每个答案。从solution(1) = 1
和solution(2) = 2
这一事实开始,您可以轻松计算出solution(3)
,solution(4)
等。根据需要计算出该数组。
这段代码足够快。
Google实施后的指示是&#34;动态编程&#34;和&#34;斐波那契序列&#34;。在这两者中,动态编程是更重要的学习内容。
答案 1 :(得分:1)
要扩展btilly的答案,假设达到n
步骤的方式数量为solution(n)
。在第一步,您可以采取步长1
并保持solution(n-1)
种方式,或采取一段2
步,并保留solution(n-2)
种方法。由于两者是互斥的,因此剩余的总方式为solution(n-1) + solution(n-2)
。
我决定使用简单的递归函数,而不是使用https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize中的memoize
类来使用memoization,而不是他所描述的“自下而上”的动态编程方法。这是我的解决方案:
import collections
import functools
class memoized(object):
'''Decorator. Caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned
(not reevaluated).
'''
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if not isinstance(args, collections.Hashable):
# uncacheable. a list, for instance.
# better to not cache than blow up.
return self.func(*args)
if args in self.cache:
return self.cache[args]
else:
value = self.func(*args)
self.cache[args] = value
return value
def __repr__(self):
'''Return the function's docstring.'''
return self.func.__doc__
def __get__(self, obj, objtype):
'''Support instance methods.'''
return functools.partial(self.__call__, obj)
class Solution(object):
@memoized
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n == 1:
return 1
elif n == 2:
return 2
else:
return self.climbStairs(n-1) + self.climbStairs(n-2)
LeetCode接受此解决方案:
答案 2 :(得分:0)
在上面的解决方案中,您通过生成它们来计算每种可能性。如果您计算recyclerView
,那么它应该等于climbStairs(35)
。所以这里让我们假设你的函数是14930352
,它计算爬上阶梯N的可能方法。
说明:解决方案中发生了什么:
f(n)
所以在这里你可以看到你一次又一次地计算相同的部分,比如// assuming f(x) = 0 where x <= 0
// and f(1) = 1 && f(2) = 2;
f(n) = f(n-1) + f(n-2);
f(n-1) = f(n-2) + f(n-3);
f(n-2) = f(n-3) + f(n-4);
.
.
.
f(2) = 2;
f(1) = 1;
和f(n-1)
。
您可以通过保存可能的组合来到达特定的楼梯X来避免这些重新计算。这是我在Java中的解决方案。使用“动态编程”方法。要计算f(n-2)
,它总共执行 35 步骤(而不是8位数的大数)。
climbStairs(35)