Матрица DP
dp := make([][]int, rows+1)
for r := range dp {
dp[r] = make([]int, cols+1)
}
Строки выделяются независимо.
Состояние зависит от двух координат: позиций в строках, клетки сетки или количества выбранных элементов.
Минимальный синтаксис, который понадобится в решении.
dp := make([][]int, rows+1)
for r := range dp {
dp[r] = make([]int, cols+1)
}
Строки выделяются независимо.
for r := 1; r <= rows; r++ {
for c := 1; c <= cols; c++ {
dp[c] = combine(dp[c], dp[c-1])
}
}
Порядок обновления критичен при сжатии памяти.
Три идиоматичных решения на Go с оценкой времени и памяти.
К клетке приходим сверху или слева.
O(rows · cols) time · O(cols) spacefunc uniquePaths(rows, cols int) int {
dp := make([]int, cols)
dp[0] = 1
for r := 0; r < rows; r++ {
for c := 1; c < cols; c++ { dp[c] += dp[c-1] }
}
return dp[cols-1]
}
Совпали символы — диагональ + 1, иначе максимум соседей.
O(a · b) time · O(b) spacefunc longestCommonSubsequence(a, b string) int {
dp := make([]int, len(b)+1)
for i := 1; i <= len(a); i++ {
diagonal := 0
for j := 1; j <= len(b); j++ {
above := dp[j]
if a[i-1] == b[j-1] { dp[j] = diagonal+1 } else { dp[j] = max(dp[j], dp[j-1]) }
diagonal = above
}
}
return dp[len(b)]
}
Каждая клетка добавляется к лучшему пути сверху или слева.
O(rows · cols) time · O(cols) spacefunc minPathSum(grid [][]int) int {
dp := make([]int, len(grid[0]))
for r := range grid {
for c := range grid[r] {
if r == 0 && c == 0 { dp[c] = grid[r][c]
} else if r == 0 { dp[c] = dp[c-1]+grid[r][c]
} else if c == 0 { dp[c] += grid[r][c]
} else { dp[c] = min(dp[c], dp[c-1])+grid[r][c] }
}
}
return dp[len(dp)-1]
}