Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/548.html

548. Split Array with Equal Sum

Level

Medium

Description

Given an array with n integers, you need to find if there are triplets (i, j, k) which satisfies following conditions:

  1. 0 < i, i + 1 < j, j + 1 < k < n - 1
  2. Sum of subarrays (0, i - 1), (i + 1, j - 1), (j + 1, k - 1) and (k + 1, n - 1) should be equal.

where we define that subarray (L, R) represents a slice of the original array starting from the element indexed L to the element indexed R.

Example:

Input: [1,2,1,2,1,2,1]

Output: True

Explanation:

i = 1, j = 3, k = 5.

sum(0, i - 1) = sum(0, 0) = 1

sum(i + 1, j - 1) = sum(2, 2) = 1

sum(j + 1, k - 1) = sum(4, 4) = 1

sum(k + 1, n - 1) = sum(6, 6) = 1

Note:

  1. 1 <= n <= 2000.
  2. Elements in the given array will be in range [-1,000,000, 1,000,000].

Solution

Several solutions exist for this problem. One solution is to use dynamic programming.

Create a 2D array dp of type Set<Integer> with nums.length rows and 5 columns, where dp[i][j] represents the possible sums when the subarray nums[0..i] is split into j parts. For 0 <= i < nums.length, dp[i][1] contains the value that equals the sum of all the elements in nums[0..i].

Then for 2 <= i < nums.length and for 2 <= j <= 4, loop over k from i to 2, and let sum be the sum of all the elements in nums[k..i]. If dp[k - 2][j - 1] contains sum, then add sum to dp[i][j].

Finally, return true if and only if dp[nums.length - 1][4] is not empty.

  • class Solution {
        public boolean splitArray(int[] nums) {
            if (nums == null || nums.length < 7)
                return false;
            int length = nums.length;
            Set<Integer>[][] dp = new Set[length][5];
            for (int i = 0; i < length; i++) {
                for (int j = 1; j <= 4; j++)
                    dp[i][j] = new HashSet<Integer>();
            }
            int sum = 0;
            for (int i = 0; i < length; i++) {
                sum += nums[i];
                dp[i][1].add(sum);
            }
            for (int i = 2; i < length; i++) {
                for (int j = 2; j <= 4; j++) {
                    sum = 0;
                    for (int k = i; k >= 2; k--) {
                        sum += nums[k];
                        if (dp[k - 2][j - 1].contains(sum))
                            dp[i][j].add(sum);
                    }
                }
            }
            return dp[length - 1][4].size() > 0;
        }
    }
    
  • Todo
    
  • class Solution:
        def splitArray(self, nums: List[int]) -> bool:
            n = len(nums)
            s = [0] * (n + 1)
            for i, v in enumerate(nums):
                s[i + 1] = s[i] + v
            for j in range(3, n - 3):
                seen = set()
                for i in range(1, j - 1):
                    if s[i] == s[j] - s[i + 1]:
                        seen.add(s[i])
                for k in range(j + 2, n - 1):
                    if s[n] - s[k + 1] == s[k] - s[j + 1] and s[n] - s[k + 1] in seen:
                        return True
            return False
    
    ############
    
    class Solution(object):
      def splitArray(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        dp = [0] * (len(nums) + 1)
        for i in range(len(nums)):
          dp[i + 1] = dp[i] + nums[i]
    
        def split(start, end):
          return set(
            [dp[mid] - dp[start] for mid in range(start + 1, end) if dp[mid] - dp[start] == dp[end + 1] - dp[mid + 1]])
    
        return any(split(0, i - 1) & split(i + 1, len(nums) - 1) for i in range(3, len(nums) - 3))
    
    

All Problems

All Solutions