Use Dynamic Programming (memoization) to get this function below 2^n time complexity

60 Views Asked by At

I have a recursive algorithm that I wrote, which splits an array and finds the minimum of the differences between the two resulting arrays. For example:

If the input array was: [1,2,2,3,3] the minimum difference would be 1. ((1+2+2) - (3+3)). If the input array was: [1,100,4,2] the minimum difference would be 93. (100 - (1+4+2)).

My algorithm is O(2^n) time complexity. I'm trying to use DP with memoization to lower the runtime.

The best that I've achieved is O(2^n / 2) using this memo that prunes half of the recursions, in the worst case. Worst case is that all sums for each level are unique.

How can I do better?

public static int minDiffRecursive(int[] nums) {
    int sum = 0;
    
    for(int num : nums) {
        sum += num;
    }
    
    int[][] memo = new int[nums.length][sum];

    for(int[] row : memo) {
        Arrays.fill(row, -1);
    }
    return move(nums, 0, 0, 0, memo);
}

private static int move(int[] nums, int i, int sum1, int sum2, int[][] memo) {
    if(i >= nums.length) return Math.abs(sum1 - sum2); //if at the end, return difference
    if(memo[i][Math.min(sum1, sum2)] > -1) return memo[i][Math.min(sum1, sum2)]; //take the min of sum1 and sum2, which are mirror images for each i. Return stored value if exists.

    int add1 = move(nums, i + 1, sum1 + nums[i], sum2, memo); //check path adding item to sum1
    int add2 = move(nums, i + 1, sum1, sum2 + nums[i], memo); //check path adding item to sum2

    return memo[i][Math.min(sum1, sum2)] = Math.min(add1, add2); //return the minimum of the two paths
}
0

There are 0 best solutions below