python - 子集总和 : Why is DFS + pruning faster than 2 for loop?

标签 python algorithm loops recursion time-complexity

本题是leetcode 416 Partition Equal Subset Sum.

#2 for loop, which got TLE
class Solution(object):
    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        nums.sort()
        allsum = sum(nums)
        if allsum % 2 == 1:
            return False
        subsets = {() : 0}
        temp = dict(subsets)
        for each in nums:
            for subset in subsets:
                new = temp[subset] + each
                if new * 2 == allsum:
                    return True
                elif new * 2 < allsum:
                    temp[tuple(list(subset) + [each])] = new
                else:
                    del temp[subset]
            subsets = dict(temp)
        return False

DFS + pruning:
class Solution(object):
    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        nums.sort()
        if sum(nums) % 2 != 0:
            return False
        else:
            target = sum(nums) / 2
        return self.path(nums, len(nums), target)

def path(self, nums, length, target):#DFS + pruning
    if target == 0:
        return True
    elif target < 0 or (target > 0 and length == 0):
        return False
    if self.path(nums, length - 1, target - nums[length - 1]):
        return True
    return self.path(nums, length - 1, target)

为什么 2 for 循环比 DFS 慢?他们都有剪枝,我觉得DFS的时间复杂度,也就是np问题,应该比2个for循环差吧?

最佳答案

仅仅因为您使用了两个循环并不意味着您的算法是 O(n2) 或多项式。算法的复杂度取决于每个循环执行了多少次。 在这部分代码中:

    for each in nums:
        for subset in subsets:
            ....

第一个循环将运行 n 次,因为 nums 的大小是 n 并且它不会改变。然而,subsets 的大小在每次迭代后都会增加 2 倍。所以你的第二个 for 循环的主体将执行 1 + 2 + 4 + 8 + 16 + 32 + ... + 2^n = 2^(n+1) 次。

所以你的算法在 O(2n) 中,甚至没有考虑昂贵的操作(复制 listdicts) 你在第二个循环的主体中执行。

您的第二种方法(从技术上讲不是 DFS)在案例复杂性方面等同于您的第一种方法。它们都是 O(n2)。但是在第二种方法中,与第一种方法(复制 listdict 等)相比,你做的额外工作更少。因此,您的第一种方法可能会运行得更快,但从长远来看并不重要。对于更大尺寸的输入,这两种方法都不够有效。

请注意,这是一个非常著名的问题,称为 Subset-sum这是NP-Complete。可以使用 Dynamic Programming 解决在 Pseudo-polynomial time .

关于python - 子集总和 : Why is DFS + pruning faster than 2 for loop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39947395/

相关文章:

python - 在 Python 中创建类似网络的图形桁架

algorithm - 学习算法骨架的一些好的起点是什么?

c# - 非结构化字符串连接策略

c - 为什么这会产生无限循环?

c - 这个 for 循环在 C 中做什么?

python - 如何在忽略索引和列标签的情况下读取 Pandas DataFrame?

python - Pyinstaller 错误 ImportError : No module named 'requests. packages.chardet.sys

python - 为什么游标没有再次创建?

c++ - 使用 for_each 和 istream_iterator 遍历 C++ 中的文本文件以查找文件名

bash - 将长列表中的数字替换为其他数字