This implementation uses Memoization Dynamic programming. This solution sacrifices space for simplicity. For me this is easier to understand and follow; in part because it is a popular/standard memorization pattern. Some simple optimizations can be made but i have elected to leave them out for a more simple solution.

```
public class Solution {
public int minPathSum(int[][] grid) {
Integer[][] memo = new Integer[grid.length][grid[0].length];
return minPath(memo,grid,0,0);
}
private int minPath(Integer[][] memo, int[][] grid, int row, int col){
if(row >= grid.length || col >= grid[0].length) return Integer.MAX_VALUE;
if(row == grid.length-1 && col == grid[0].length-1) return grid[row][col];
if(memo[row][col] == null) memo[row][col] = Math.min(minPath(memo,grid,row+1,col),minPath(memo,grid,row,col+1)) + grid[row][col];
return memo[row][col];
}
}
```