Systematic Inefficiency in LeetCode Official Solutions

I have noticed a systematic issue in many dynamic programming (DP) related offical solutions. It is often possible to optimize the memory consumption of DP solutions by reducing dimensions of the DP table. Most of the time, this boils down onto keeping two snapshots: the values from the previous iteration and those set in the current one. Nonetheless, this is where the wrong pattern frequently occurs (see, for an example, the official solution of the Out of Boundary Paths problem).

If the current iteration sets all elements of a table based upon previous values, then it is a waste of time to create a temporary table at each iteration (it will soon or later trigger expensive gargabe collection sessions). It is much more efficient to create 2 tables at the beginning and only swap pointers. For the sake of completeness, below is the version using this approach for the previously mentioned problem. It also contains an additional optimization by introducing extra boundary elements to avoid special handling of edge cells. The boundary cells are initialized for the single move case and each iteration calculates the number of paths for a given number of moves.

class Solution {
    private static final int MODULUS = 1_000_000_007; 
    
    public int findPaths(int m, int n, int maxMove, int startRow, int startColumn) {
        if (maxMove == 0)
            return 0;
        
        var prev = new int[m + 2][n + 2];
        var curr = new int[m + 2][n + 2];

        for (var i = 1; i <= m; i++) {
            prev[i][1]++;
            prev[i][n]++;
        }
        for (var i = 1; i <= n; i++) {
            prev[1][i]++;
            prev[m][i]++;
        }
        startRow++;
        startColumn++;
        
        var totalPaths = prev[startRow][startColumn];

        for (var move = 2; move <= maxMove; move++) {
            for (var i = 1; i <= m; i++)
                for (var j = 1; j <= n; j++)
                    curr[i][j] = ((prev[i - 1][j] + prev[i + 1][j]) % MODULUS + 
                                  (prev[i][j - 1] + prev[i][j + 1]) % MODULUS) % MODULUS;
            
            totalPaths = (totalPaths + curr[startRow][startColumn]) % MODULUS;
            var temp = prev;
            prev = curr;
            curr = temp;
        }
        
        return totalPaths;
    }
}
Comments (0)