Dynamic Programming Algorithm with Space Compression Optimization and different ways to shallow copy a array list

2023-07-13 20:30:16
Using dynamic programming algorithm with space compression optimization and different ways to shallow copy a Array List, solving the "931. Minimum Falling Path Sum"

Example

Shallow copy arrays in different programming languages

[].slice(start, end) // Index - 1 from end, could exceed the boundary
copy(dst, src)
array_slice([], $start, $length) // Index -1 from end, could exceed the boundary
int[] src= {}
Arrays.copyOfRange(src, start, end) // Index -1 will throw error, better not exceed the boundary
Array.copy(src, srcStart, dst, dstStart, length) 
dst = src;
vector<int>(src.begin() + srcStart, src.begin() + srcEnd);
memcpy(dst, src + srcStart, sizeof(int) * length) 
dst = copy.copy(src)

931. Minimum Falling Path Sum

Given an n x n array of integers matrix, return the minimum sum of any falling path through matrix.
A falling path starts at any element in the first row and chooses the element in the next row that is either directly below or diagonally left/right. Specifically, the next element from position (row, col) will be (row + 1, col - 1), (row + 1, col), or (row + 1, col + 1).
Example 1:

Input: matrix = [[2,1,3],[6,5,4],[7,8,9]]
Output: 13
Explanation: There are two falling paths with a minimum sum as shown.

Answers

Dynamic programming algorithm with copying array

var minFallingPathSum = function(matrix) {
  const n = matrix.length, dp = matrix[0], prev = dp.slice()
  for (let row = 1; row < n; row++) {
    for (let col = 0; col < n; col++) {
      dp[col] = Math.min.apply(null, prev.slice(Math.max(col - 1, 0), col + 2)) + matrix[row][col]
    }
    prev.length = 0
    prev.push(...dp)
  }
  return Math.min.apply(null, dp)
};
function minFallingPathSum(matrix: number[][]): number {
  const n = matrix.length, dp = matrix[0]
  let prev = dp.slice()
  for (let row = 1; row < n; row++) {
    for (let col = 0; col < n; col++) {
      dp[col] = Math.min.apply(null, prev.slice(Math.max(col - 1, 0), col + 2)) + matrix[row][col]
    }
    prev = dp.slice()
  }
  return Math.min.apply(null, dp)
};
func minFallingPathSum(matrix [][]int) int {
  n := len(matrix)
  dp := matrix[0][:]
  prev := make([]int, n)
  copy(prev, dp) 
  for row := 1; row < n; row++ {
    for col := 0; col < n; col++ {
      dp[col] = min(prev[max(col - 1, 0): min([]int{col + 2, n})]) + matrix[row][col]
    }
    copy(prev, dp)
  }
  return min(dp)
}
func min(ar []int) int {
  ans := int(^uint(0) >> 1)
  for _, num := range ar {
    if num < ans {
      ans = num
    }
  }
  return ans
}
func max(a, b int) int {
  if a > b {
    return a
  }
  return b
}
class Solution {
  function minFallingPathSum($matrix) {
    $n = count($matrix);
    $dp = $matrix[0];
    $prev = array_slice($dp, 0);
    for ($row = 1; $row < $n; $row++) {
      for ($col = 0; $col < $n; $col++) {
        $dp[$col] = min(array_slice($prev, max($col - 1, 0), $col === 0 ? 2 : 3)) + $matrix[$row][$col];
      }
      $prev = array_slice($dp, 0);
    }
    return min($dp);
  }
}
class Solution {
  public int minFallingPathSum(int[][] matrix) {
    int n = matrix.length;
    int[] dp = matrix[0];
    int[] prev = Arrays.copyOfRange(dp, 0, n);
    for (int row = 1; row < n; row++) {
      for (int col = 0; col < n; col++) {
        dp[col] = Arrays.stream(Arrays.copyOfRange(prev, Math.max(col - 1, 0), Math.min(col + 2, n))).min().getAsInt() + matrix[row][col];
      }
      prev = Arrays.copyOfRange(dp, 0, n);
    }
    return Arrays.stream(dp).min().getAsInt();
  }
}
public class Solution {
  public int MinFallingPathSum(int[][] matrix) {
    int n = matrix.Length;
    int[] dp = matrix[0];
    int[] prev = new int[n];
    Array.Copy(dp, 0, prev, 0, n);
    Console.WriteLine(string.Join(',', dp));
    for (int row = 1; row < n; row++) {
      for (int col = 0; col < n; col++) {
        int len = col == 0 || col == n - 1 ? 2  : 3;
        int[] dst = new int[len];
        Array.Copy(prev, Math.Max(col - 1, 0), dst, 0, len);
        dp[col] = dst.Min() + matrix[row][col];
      }
      Array.Copy(dp, 0, prev, 0, n);
    }
    return dp.Min();
  }
}
class Solution {
public:
  int minFallingPathSum(vector<vector<int>>& matrix) {
    int n = matrix.size();
    vector<int> prev(matrix[0].begin(), matrix[0].end());
    vector<int> dp(prev.begin(), prev.end());
    for (int row = 1; row < n; row++) {
      for (int col = 0; col < n; col++) {
        dp[col] = *min_element(prev.begin() + max(col - 1, 0), prev.begin() + min(col + 2, n)) + matrix[row][col];
      }
      prev = dp;
    }
    return *min_element(dp.begin(), dp.end());
  }
};
#define MAX(a, b) (a > b ? a : b)
int min(int* ar, int n) {
  int ans = INT_MAX;
  for (int i = 0; i < n; i++) {
    if (ans > ar[i]) ans = ar[i];
  }
  return ans;
}
int minFallingPathSum(int** matrix, int matrixSize, int* matrixColSize){
  int* prev = malloc(sizeof(int) * matrixSize);
  memcpy(prev, matrix[0], sizeof(int) * matrixSize);
  for (int col = 0; col < matrixSize; col++) prev[col] = matrix[0][col];
  int* dp = malloc(sizeof(int) * matrixSize);
  memcpy(dp, prev, sizeof(int) * matrixSize);
  for (int row = 1; row < matrixSize; row++) {
    for (int col = 0; col < matrixSize; col++) {
      int len = col == 0 || col == matrixSize - 1 ? 2 : 3;
      int* dst = malloc(sizeof(int) * len);
      memcpy(dst, prev + MAX(col - 1, 0), sizeof(int) * len);
      dp[col] = min(dst, len) + matrix[row][col];
    }
    memcpy(prev, dp, sizeof(int) * matrixSize);
  }
  return min(dp, matrixSize);
}
class Solution:
  def minFallingPathSum(self, matrix: List[List[int]]) -> int:
    n, dp = len(matrix), matrix[0]
    prev = copy.copy(dp)
    for row in range(1, n):
      for col in range(0, n):
        dp[col] = min(prev[max(col - 1, 0) : col + 2]) + matrix[row][col]
      prev = copy.copy(dp)
    return min(dp)

Dynamic Programming Algorithm With Space Compression Optimization to solve "1911. Maximum Alternating Subsequence Sum"
Using dynamic programming algorithm with space compression optimization to solve the "1911. Maximum Alternating Subsequence Sum" problem.
A simple and efficient way to check Toeplitz matrix which always has the same row and column along its main diagonal
How to check if a special Toeplitz matrix, which has the same row and column along its main diagonal, is symmetric along its main diagonal using a simple and efficient method?
动态规划 + 状态压缩 + bitCount 统计二进制 1 个数,求解《1681. 最小不兼容性》
Go / Java / C# / C / C++ / Python / PHP 内置 bitCount,动态规划 + 状态压缩,求解《1681. 最小不兼容性》