BiruLyu
7/6/2017 - 12:17 AM

548. Split Array with Equal Sum(1st).java

public class Solution {
    public boolean splitArray(int[] nums) {
        if (nums == null || nums.length < 7) return false;
        int len = nums.length;
        int[] prefixSum = new int[len];
        prefixSum[0] = nums[0];
        for (int i = 1; i < len; i++) {
            prefixSum[i] =  prefixSum[i - 1] + nums[i];
        }
        for (int j = 3; j < len - 3; j++) {
            Set<Integer> set = new HashSet<>();
            for (int i = 1; i < j - 1; i++) {
                int first = prefixSum[i - 1] ;
                int second = prefixSum[j - 1] - prefixSum[i];
                if (first == second) {
                    set.add(first);
                }
            }
            for (int k = j + 2; k < len - 1; k++) {
                int third = prefixSum[k - 1] - prefixSum[j];
                int fourth = prefixSum[len - 1] - prefixSum[k];
                if ( third == fourth && set.contains(third)) {
                    return true;
                }
            }
        }
        return false;
    }
}
public class Solution {
    //Here j is used for middle cut, i for left cut and k for right cut.
    //Iterate middle cuts and then find left cuts which divides the first half into two equal quarters, store that quarter sums             in the hashset. Then find right cuts which divides the second half into two equal quarters and check if quarter sum is           present in the hashset. If yes return true.
    public boolean splitArray2(int[] nums) {
        if (nums.length < 7)
            return false;
        int[] sum = new int[nums.length];
        sum[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            sum[i] = sum[i - 1] + nums[i];
        }
        for (int j = 3; j < nums.length - 3; j++) {
            HashSet < Integer > set = new HashSet < > ();
            for (int i = 1; i < j - 1; i++) {
                if (sum[i - 1] == sum[j - 1] - sum[i])
                    set.add(sum[i - 1]);
            }
            for (int k = j + 2; k < nums.length - 1; k++) {
                if (sum[nums.length - 1] - sum[k] == sum[k - 1] - sum[j] && set.contains(sum[k - 1] - sum[j]))
                    return true;
            }
        }
        return false;
    }
    
    //can give a sum boundary to accelerate the search
    public boolean splitArray(int[] nums) {
        int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE, n = nums.length;
        int[] sum = new int[n];
        sum[0] = nums[0];
        for(int i = 0; i < n; ++i) {
            min = Math.min(min, nums[i]);
            max = Math.max(max, nums[i]);
            if(i > 0) sum[i] = sum[i-1] + nums[i];
        }
        int minSum = sum[n-1]-3*max, maxSum = sum[n-1]-3*min;
        minSum = minSum < 0? minSum/4: (minSum+3)/4;
        maxSum = maxSum > 0? maxSum/4: (maxSum-3)/4;
        for(int i = 0; i < n - 6; ++i) {
            //filter out unnecessary search by specifies the sum boundary
            if(sum[i] >= minSum && sum[i] <= maxSum) {
                int curr = sum[i];
                for(int j = i + 2; j < n - 4; ++j) {
                    if(sum[j] - sum[i+1] == curr) {
                        for(int k = j + 2; k < n - 2; ++k) {
                            if(sum[k] - sum[j+1] == curr && sum[n-1] - sum[k+1] == curr) return true; 
                        }
                    }
                }
            }
        }
        return false;
    }
}