416. Partition Equal Subset Sum.md 2.0 KB
Newer Older
K
KEQI HUANG 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
### 416.  Partition Equal Subset Sum



题目:
<https://leetcode.com/problems/partition-equal-subset-sum/>

难度:

Medium 

记得算法考试考过证明这个问题是NP的,当时用的是subset sum是NP,然后来证明这个?如果我们能找到一个subset的sum是整个array sum的一半,那么问题解决。subset sum我们又可以继续转化,转成背包问题。

值得注意的是,这是subset sum,并不是subarray sum(这个明显要简单一些,因为subarray是连着的).

subset sum也是有自己的[wikipedia page](https://en.wikipedia.org/wiki/Subset_sum_problem).



当然,这也是一个subset problem,我们当然也可以用subset,加入和不加入,但是worst case O(2^n).



对于subset sum的递推方程式:

subset(arr,n,s) = subset(arr,n-1,s) or subset(arr, n-1, s- arrp[n-1])



画表可以开始,第一列全为1,是因为不选全部可以为0



```
	0	1	2	3	4	5	6	8	9	10	11
0	1	0	0	0	0	0	0	0	0	0	0
1	1	1	0	0	0	0	0	0	0	0	0
5	1	1	0	0	0	1	1	0	0	0	0
5	1	1	0	0	0	1	1	0	0	0	1
```



所以伪多项式算法写出来

AC代码



```
class Solution(object):
    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        def subset(nums, s):
        	dp = [[0 for i in range(s+1) ] for j in range(len(nums)+1)]

        	dp[0][0] = 1
        	# init the first col
        	for i in range(len(nums)+1 
        		dp[i][0] = 1

        	for i in range(1,len(nums)+1):
        		for j in range(1,s+1):
        			if dp[i-1][j] == 1:
        				dp[i][j] = 1
        			elif j >= nums[i-1] and dp[i-1][j-nums[i-1]] ==1:
        				dp[i][j]  = 1
        	return dp[-1][-1] == 1



        total = sum(nums)
        if total % 2 == 1:
        	return False
        else:
        	half = total / 2
        	return subset(nums,half) == 1

```



当然可以小调整,比如一旦发现,提前return等等,但是时间上依旧是后20%,不知道时间上快很多的人是如何做到的|||