蛙跳记忆(Python)
Frog Jump Memoization(Python)
下面是问题描述,然后是使用Python的递归解决方案。
该解决方案效率低下。我知道使用记忆,我们可以改进这个解决方案。
我也在 Whosebug 上遇到过类似的问题,但我无法找到解决方案。我对记忆技术还很陌生。
如果有人可以帮助我解决使用记忆的问题,那将非常有帮助。
问题描述:
一只青蛙正在过河。这条河被分成一些单元,在每个单元中,可能有也可能没有石头。青蛙可以跳到石头上,但不能跳进水里。
给定一个按升序排列的石头位置列表(以单位为单位),判断青蛙是否可以落在最后一块石头上过河。最初,青蛙在第一块石头上,并假设第一次跳跃必须是 1 个单位。
如果青蛙的上一次跳跃是 k 个单位,那么它的下一次跳跃必须是 k - 1、k 或 k + 1 个单位。青蛙只能向前跳
Examples
下面是我使用递归的解决方案(Python)。
class Solution:
def canCross(self, stones: List[int]) -> bool:
return self.helper(stones[0],stones,1)
def helper(self,curr,stones,k):
if curr+k == stones[-1]:
return True
if not curr+k in stones or k<=0:
return False
else:
curr = curr+k
return self.helper(curr,stones,k-1) or self.helper(curr,stones,k) or self.helper(curr,stones,k+1)
@克里希纳,
请试试这个 memo
版本,看看速度是否加快。
def canCross(self, stones: List[int]) -> bool:
if stones[1] != 1:
return False
d = {x: set() for x in stones}
d[1].add(1)
for x in stones[:-1]:
for j in d[x]:
for k in range(j-1, j+2):
if k > 0 and x+k in d:
d[x+k].add(k)
return bool(d[stones[-1]])
这里出现了更快的 memo
版本,它比以前的版本更快。它快了大约 50%...
class Solution:
"""
"""
def canCross(self, stones: List[int]) -> bool:
self.target = stones[-1]
stones = set(stones)
return self.dfs(stones, 0, 0, {})
def dfs(self, stones, cur, k, memo):
if cur == self.target:
return True
if (cur, k) in memo:
return memo[(cur, k)]
for nxt in [k-1, k, k+1]:
if nxt > 0 and cur + nxt in stones:
if self.dfs(stones, cur+nxt, nxt, memo):
memo[(cur, k)] = True
return True
memo[(cur, k)] = False
return False
functools
类:
中方法记忆的装饰器
from functools import cached_property
class Solution:
def canCross(self, stones: List[int]) -> bool:
return self.helper(stones[0],stones,1)
@cached_property
def helper(self,curr,stones,k):
if curr+k == stones[-1]:
return True
if not curr+k in stones or k<=0:
return False
else:
curr = curr+k
return self.helper(curr,stones,k-1) or self.helper(curr,stones,k) or self.helper(curr,stones,k+1)
下面是问题描述,然后是使用Python的递归解决方案。 该解决方案效率低下。我知道使用记忆,我们可以改进这个解决方案。 我也在 Whosebug 上遇到过类似的问题,但我无法找到解决方案。我对记忆技术还很陌生。 如果有人可以帮助我解决使用记忆的问题,那将非常有帮助。
问题描述: 一只青蛙正在过河。这条河被分成一些单元,在每个单元中,可能有也可能没有石头。青蛙可以跳到石头上,但不能跳进水里。
给定一个按升序排列的石头位置列表(以单位为单位),判断青蛙是否可以落在最后一块石头上过河。最初,青蛙在第一块石头上,并假设第一次跳跃必须是 1 个单位。
如果青蛙的上一次跳跃是 k 个单位,那么它的下一次跳跃必须是 k - 1、k 或 k + 1 个单位。青蛙只能向前跳
Examples
下面是我使用递归的解决方案(Python)。
class Solution:
def canCross(self, stones: List[int]) -> bool:
return self.helper(stones[0],stones,1)
def helper(self,curr,stones,k):
if curr+k == stones[-1]:
return True
if not curr+k in stones or k<=0:
return False
else:
curr = curr+k
return self.helper(curr,stones,k-1) or self.helper(curr,stones,k) or self.helper(curr,stones,k+1)
@克里希纳,
请试试这个 memo
版本,看看速度是否加快。
def canCross(self, stones: List[int]) -> bool:
if stones[1] != 1:
return False
d = {x: set() for x in stones}
d[1].add(1)
for x in stones[:-1]:
for j in d[x]:
for k in range(j-1, j+2):
if k > 0 and x+k in d:
d[x+k].add(k)
return bool(d[stones[-1]])
这里出现了更快的 memo
版本,它比以前的版本更快。它快了大约 50%...
class Solution:
"""
"""
def canCross(self, stones: List[int]) -> bool:
self.target = stones[-1]
stones = set(stones)
return self.dfs(stones, 0, 0, {})
def dfs(self, stones, cur, k, memo):
if cur == self.target:
return True
if (cur, k) in memo:
return memo[(cur, k)]
for nxt in [k-1, k, k+1]:
if nxt > 0 and cur + nxt in stones:
if self.dfs(stones, cur+nxt, nxt, memo):
memo[(cur, k)] = True
return True
memo[(cur, k)] = False
return False
functools
类:
from functools import cached_property
class Solution:
def canCross(self, stones: List[int]) -> bool:
return self.helper(stones[0],stones,1)
@cached_property
def helper(self,curr,stones,k):
if curr+k == stones[-1]:
return True
if not curr+k in stones or k<=0:
return False
else:
curr = curr+k
return self.helper(curr,stones,k-1) or self.helper(curr,stones,k) or self.helper(curr,stones,k+1)