Teaching Kids Programming – Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm)


Teaching Kids Programming: Videos on Data Structures and Algorithms

Given a non-empty array nums containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.

Example 1:
Input: nums = [1,5,11,5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].

Example 2:
Input: nums = [1,2,3,5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.

Constraints:
1 <= nums.length <= 200
1 <= nums[i] <= 100

Technically we can apply bruteforce algorithms to solve this if the input size is small. There are tex_7da98591b3d78eeec743ae932ec8bcb8 Teaching Kids Programming - Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm) algorithms dynamic programming teaching kids programming youtube video subsequences/subset and checking each to see if it sums up to half takes O(N) time and thus overall time complexity is tex_927f1f18f03846bde511ae269f07007b Teaching Kids Programming - Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm) algorithms dynamic programming teaching kids programming youtube video

The optimal solution is to use Dynamic Programming algorithm. Yesterday we talked about Top Down Dynamic Programming Algorithm to solve the equation dp(i, j) which means the possibility to have a subset sum to j with elements up to [:i+1] or [i:].

tex_5e52c6877dbc58255b44b49f783437da Teaching Kids Programming - Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm) algorithms dynamic programming teaching kids programming youtube video for k in nums,
or:
tex_a2069c24506de03101a943515d02d4c8 Teaching Kids Programming - Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm) algorithms dynamic programming teaching kids programming youtube video for k in nums.

Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm)

We can save the DP values in two dimension array then start filling the values bottom up. The outer loop is the index of the numbers, and the inner loop is the subset sum. If dp[i] requires dp[i+1], we need to iterate the index backwards/downwards.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
    def canPartition(self, nums: List[int]) -> bool:        
        total = sum(nums)
        if total & 1:
            return False
        half = total // 2
        dp = [[False] * (half + 1) for _ in range(n + 1)]        
        for i in range(n):
            dp[i][0] = True                
        for i in range(n - 2, -1, -1):
            for j in range(half, -1, -1):
                if j < nums[i]:
                    dp[i][j] = dp[i + 1][j]
                else:
                    dp[i][j] = dp[i + 1][j] or dp[i + 1][j - nums[i]]                    
        return dp[0][half]
class Solution:
    def canPartition(self, nums: List[int]) -> bool:        
        total = sum(nums)
        if total & 1:
            return False
        half = total // 2
        dp = [[False] * (half + 1) for _ in range(n + 1)]        
        for i in range(n):
            dp[i][0] = True                
        for i in range(n - 2, -1, -1):
            for j in range(half, -1, -1):
                if j < nums[i]:
                    dp[i][j] = dp[i + 1][j]
                else:
                    dp[i][j] = dp[i + 1][j] or dp[i + 1][j - nums[i]]                    
        return dp[0][half]

If the dp[i] is based on dp[i-1], then we need to iterate the index forwards/upwards.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
    def canPartition(self, nums: List[int]) -> bool:        
        total = sum(nums)
        if total & 1:
            return False
        half = total // 2
    
        dp = [[False] * (half + 1) for _ in range(n + 1)]        
        for i in range(n):
            dp[i][0] = True     
        for i in range(1, n):
            for j in range(half, -1, -1):
                if j < nums[i]:
                    dp[i][j] = dp[i - 1][j]
                else:
                    dp[i][j] = dp[i - 1][j] or dp[i - 1][j - nums[i]]
        return dp[n - 1][half]       
class Solution:
    def canPartition(self, nums: List[int]) -> bool:        
        total = sum(nums)
        if total & 1:
            return False
        half = total // 2
    
        dp = [[False] * (half + 1) for _ in range(n + 1)]        
        for i in range(n):
            dp[i][0] = True     
        for i in range(1, n):
            for j in range(half, -1, -1):
                if j < nums[i]:
                    dp[i][j] = dp[i - 1][j]
                else:
                    dp[i][j] = dp[i - 1][j] or dp[i - 1][j - nums[i]]
        return dp[n - 1][half]       

Both time complexity is O(SN) where S is the subset sum (half) and N is the number of elements in the given array. The space complexity is O(SN).

Partition Equal Subset Sum via Optimised 1D Bottom Up Dynamic Programming Algorithm

dp[i] is purely based on dp[i-1] or dp[i+1], so we can compress the DP to one dimensional. To avoid conflicts of updating the dp value, we need to iterate the sum downwards.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
    def canPartition(self, nums: List[int]) -> bool:        
        total = sum(nums)
        if total & 1:
            return False
        half = total // 2                    
        n = len(nums)
       
        dp = [True] + [False] * half
        for j in nums:
            for i in range(half, 0, -1):
                if j <= i:
                    dp[i] = dp[i] | dp[i - j]
        return dp[half]   
class Solution:
    def canPartition(self, nums: List[int]) -> bool:        
        total = sum(nums)
        if total & 1:
            return False
        half = total // 2                    
        n = len(nums)
       
        dp = [True] + [False] * half
        for j in nums:
            for i in range(half, 0, -1):
                if j <= i:
                    dp[i] = dp[i] | dp[i - j]
        return dp[half]   

The time complexity is O(SN) and the space complexity is O(S).

Partition Equal Subset Sum Algorithms

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
997 words
Last Post: Teaching Kids Programming - Find Partition Equal Subset Sum (Top Down Dynamic Programming Algorithm)
Next Post: Teaching Kids Programming - Split Tree to Maximize Product (Recursive Depth First Search Algorithm)

The Permanent URL is: Teaching Kids Programming – Find Partition Equal Subset Sum (Bottom Up Dynamic Programming Algorithm)

Leave a Reply