记忆递归调用时效率差异巨大
在做这个LeetCode问题时,我注意到有很大的不同性能取决于我决定编码的版本(请参阅注释的部分)。其中之一更简洁,但我看不出有什么区别。如有解释,将不胜感激。
class Solution:
def rec_memo(self, nums, index, curr_sum, target, memo):
if curr_sum == target:
return True
elif curr_sum > target or index == len(nums):
return False
if (index, curr_sum) in memo:
return memo[(index, curr_sum)]
# This line (below) is significantly more efficient
# memo[(index, curr_sum)] = self.rec_memo(nums, index + 1, curr_sum + nums[index], target, memo) or self.rec_memo(nums, index + 1, curr_sum, target, memo)
# These lines (below) are significantly less efficient
# choose_num = self.rec_memo(nums, index + 1, curr_sum + nums[index], target, memo)
# not_choose_num = self.rec_memo(nums, index + 1, curr_sum, target, memo)
# memo[(index, curr_sum)] = choose_num or not_choose_num
return memo[(index, curr_sum)]
def canPartition(self, nums: List[int]) -> bool:
sum = 0
for i in range(0, len(nums), 1):
sum += nums[i]
if sum % 2 != 0:
return False
memo = {}
return self.rec_memo(nums, 0, 0, sum // 2, memo)
While doing this LeetCode problem, I noticed that there was a big difference in performance depending on which version I decided to code (see the part that is commented). One of them is more succinct, but I don't see a reason why there should be a difference. An explanation would be greatly appreciated.
class Solution:
def rec_memo(self, nums, index, curr_sum, target, memo):
if curr_sum == target:
return True
elif curr_sum > target or index == len(nums):
return False
if (index, curr_sum) in memo:
return memo[(index, curr_sum)]
# This line (below) is significantly more efficient
# memo[(index, curr_sum)] = self.rec_memo(nums, index + 1, curr_sum + nums[index], target, memo) or self.rec_memo(nums, index + 1, curr_sum, target, memo)
# These lines (below) are significantly less efficient
# choose_num = self.rec_memo(nums, index + 1, curr_sum + nums[index], target, memo)
# not_choose_num = self.rec_memo(nums, index + 1, curr_sum, target, memo)
# memo[(index, curr_sum)] = choose_num or not_choose_num
return memo[(index, curr_sum)]
def canPartition(self, nums: List[int]) -> bool:
sum = 0
for i in range(0, len(nums), 1):
sum += nums[i]
if sum % 2 != 0:
return False
memo = {}
return self.rec_memo(nums, 0, 0, sum // 2, memo)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
第一个:
如果第一个返回
True
,则不会评估后一个对self.rec_memo()
的调用,因为 短路评估。但是,对于第二个:
无论第一次调用
rec_memo()
的结果如何,您都将始终进行第二次递归调用。您观察到的速度减慢可能是这些额外的递归调用的结果。The first one:
won't evaluate the latter call to
self.rec_memo()
if the first one returnsTrue
, due to short-circuit evaluation.However, with the second one:
you'll always make the second recursive call, no matter the result of the first call to
rec_memo()
. The slowdown you're observing is likely the result of these additional recursive calls.