记忆递归调用时效率差异巨大

发布于 2025-01-09 13:57:48 字数 1404 浏览 0 评论 0原文

在做这个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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一桥轻雨一伞开 2025-01-16 13:57:48

第一个:

self.rec_memo(nums, index + 1, curr_sum + nums[index], target, memo) or \
self.rec_memo(nums, index + 1, curr_sum, target, memo)

如果第一个返回 True,则不会评估后一个对 self.rec_memo() 的调用,因为 短路评估

但是,对于第二个:

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

无论第一次调用 rec_memo() 的结果如何,您都将始终进行第二次递归调用。您观察到的速度减慢可能是这些额外的递归调用的结果。

The first one:

self.rec_memo(nums, index + 1, curr_sum + nums[index], target, memo) or \
self.rec_memo(nums, index + 1, curr_sum, target, memo)

won't evaluate the latter call to self.rec_memo() if the first one returns True, due to short-circuit evaluation.

However, with the second one:

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文