Skip to content

Completed DP-3 Assignment#1535

Open
Hriday-A wants to merge 1 commit into
super30admin:masterfrom
Hriday-A:master
Open

Completed DP-3 Assignment#1535
Hriday-A wants to merge 1 commit into
super30admin:masterfrom
Hriday-A:master

Conversation

@Hriday-A

Copy link
Copy Markdown

No description provided.

@super30admin

Copy link
Copy Markdown
Owner

Least Falling Path Sum (Minimum_Falling_Path_Sum.java)

Your approach to use memoization is correct and improves the time complexity from exponential to polynomial. However, there are a few issues to address:

  1. Base Case Handling:

    • The base case for j < 0 || j >= n should return a large value (like Integer.MAX_VALUE) to indicate an invalid path. However, you must be cautious about integer overflow when adding to this value. Since the problem constraints state that values in the matrix are between -100 and 100, and n is at most 100, the maximum absolute value of the path sum is 100*100 = 10000. So, returning Integer.MAX_VALUE is safe because it is much larger than 10000. Your current return value Integer.MAX_VALUE - 10 is also large enough, but it's better to use Integer.MAX_VALUE for clarity and to avoid any potential issues.
    • The order of base cases matters: you should first check if j is out of bounds, then check if i has reached the end. Otherwise, when i == n and j is out of bounds, you might return 0 instead of an invalid value.
  2. Recursion Stack:

    • The recursion depth is n, which is acceptable since n <= 100. However, you could consider an iterative dynamic programming approach to avoid recursion overhead and stack overflow for very large n (though n=100 is manageable).
  3. Memo Initialization:

    • You initialized the memo table with Integer[n][n], which is correct. Remember to check for null in the memo table before recursing.
  4. Edge Cases:

    • Your code handles the null or empty matrix correctly.

Suggested correction for the base cases:

private int helper(int[][] matrix, int i, int j) {
    int n = matrix.length;
    // Check if j is out of bounds first
    if (j < 0 || j >= n) {
        return Integer.MAX_VALUE;
    }
    // Then check if we have reached the last row
    if (i == n - 1) {
        return matrix[i][j];
    }
    if (memo[i][j] != null) {
        return memo[i][j];
    }
    int down = helper(matrix, i + 1, j);
    int downLeft = helper(matrix, i + 1, j - 1);
    int downRight = helper(matrix, i + 1, j + 1);
    memo[i][j] = matrix[i][j] + Math.min(down, Math.min(downLeft, downRight));
    return memo[i][j];
}

Note: In the base case when i == n-1, we should return matrix[i][j] because it's the last row. The original base case if (i == n) return 0; was incorrect because when i is the last row (index n-1), we should return the value at that cell. The recursive calls should stop at the last row.

Alternatively, you can keep the base case as if (i == n) return 0; but then you are effectively processing rows from 0 to n-1 and then adding 0 at the end. However, that would require the recursive function to go to i = n. But in your code, you are calling helper(matrix, 0, j), which starts at row 0. When i becomes n, you have processed all rows. So the base case if (i == n) return 0; is correct. But then you must ensure that when i is n, you don't access matrix[i][j] because that would be out of bounds. So the base case for j out of bounds should be checked first.

Actually, the original reference solution has:

if (j < 0 || j >= n) {
    return Integer.MAX_VALUE;
}
if (i == n) {
    return 0;
}

This is correct. So your base case for i == n is correct, but you should return 0. However, in your code, you have:

if (j<0 || j>=n) return Integer.MAX_VALUE -10;
if (i==n) return 0;

This is almost correct, but the value returned for out-of-bound should be Integer.MAX_VALUE (without subtracting 10) to avoid any chance of overflow when adding. Since the maximum path sum is bounded by 10000, Integer.MAX_VALUE is safe.

Also, note that in the base case when i == n, we are at the row beyond the last, so we return 0. Then the recursive function for the last row (i = n-1) will compute:
matrix[n-1][j] + min(0, ...)
which is correct.

So your base cases are almost correct, but the out-of-bound return value should be Integer.MAX_VALUE instead of Integer.MAX_VALUE - 10.

  1. Final Verdict: With the base case fixed, your solution should be correct. The time and space complexity are optimal for a memoized solution.

VERDICT: NEEDS_IMPROVEMENT


Delete and Earn (Delete_and_earn.java)

Your solution is well-structured and follows the dynamic programming approach correctly. However, you need to handle the edge case where the maximum value in nums is 0. In such a case, your code will try to access arr[1] when initializing dp[1], but arr has length 1 (index 0 only), causing an ArrayIndexOutOfBoundsException.

To fix this, you should check if max is at least 1 before initializing dp[1]. Alternatively, you can initialize the dp array with a size of max+1 and then handle the cases where max is 0 or 1 separately.

Here's a corrected version:

class Solution {
    public int deleteAndEarn(int[] nums) {
        int max = 0;
        for (int num : nums) {
            max = Math.max(max, num);
        }
        int[] arr = new int[max + 1];
        for (int num : nums) {
            arr[num] += num;
        }
        if (max == 0) {
            return arr[0];
        }
        int[] dp = new int[max + 1];
        dp[0] = arr[0];
        if (max == 1) {
            return Math.max(arr[0], arr[1]);
        }
        dp[1] = Math.max(arr[0], arr[1]);
        for (int i = 2; i <= max; i++) {
            dp[i] = Math.max(dp[i - 1], arr[i] + dp[i - 2]);
        }
        return dp[max];
    }
}

Alternatively, you can use a more general approach without multiple conditionals by ensuring that the dp array is built only for indices that exist. Another common approach is to use a dp array that starts from index 0 and goes to max, and then handle the base cases within the loop by checking the index.

Your code is almost correct, and with this small fix, it will handle all cases. Keep up the good work!

VERDICT: NEEDS_IMPROVEMENT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants