Skip to content

Commit c62ff9b

Browse files
committed
- MinimumFallingPathSum
Signed-off-by: Gopal S Akshintala <[email protected]>
1 parent 087797f commit c62ff9b

File tree

6 files changed

+66
-32
lines changed

6 files changed

+66
-32
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package practice.dp;
2+
3+
import java.util.Arrays;
4+
5+
/* 26 Oct 2025 21:20 */
6+
7+
/** [931. Minimum Falling Path Sum](https://leetcode.com/problems/minimum-falling-path-sum/) */
8+
public class MinimumFallingPathSum {
9+
public int minFallingPathSum(int[][] matrix) {
10+
var table = matrix[0].clone(); // ! Clone to avoid mutating input
11+
for (var row = 1; row < matrix.length; row++) {
12+
var prev = table[0]; // ! Store previous column value before overwriting
13+
for (var col = 0; col < matrix[0].length; col++) {
14+
var temp = table[col]; // ! Save current value before overwriting
15+
if (col == 0) {
16+
table[col] = matrix[row][col] + Math.min(table[col], table[col + 1]);
17+
} else if (col == matrix[0].length - 1) {
18+
table[col] = matrix[row][col] + Math.min(table[col], prev);
19+
} else {
20+
table[col] = matrix[row][col] + Math.min(table[col], Math.min(prev, table[col + 1]));
21+
}
22+
prev = temp; // ! Move to next column
23+
}
24+
}
25+
return Arrays.stream(table).min().orElseThrow();
26+
}
27+
28+
static void main() {
29+
var l = new MinimumFallingPathSum();
30+
System.out.println(l.minFallingPathSum(new int[][] {{2, 1, 3}, {6, 5, 4}, {7, 8, 9}})); // 13
31+
System.out.println(l.minFallingPathSum(new int[][] {{-19, 57}, {-40, -5}})); // -59
32+
}
33+
}
Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,8 @@
11
/* gakshintala created on 12/29/19 */
22
package leetcode.dp
33

4-
/** https://leetcode.com/problems/minimum-path-sum/ */
5-
fun minPathSumRecursive(
6-
grid: Array<IntArray>,
7-
row: Int = grid.lastIndex,
8-
col: Int = grid[0].lastIndex,
9-
cache: MutableMap<Pair<Int, Int>, Int> = mutableMapOf(),
10-
): Int {
11-
cache[row to col]?.let {
12-
return it
13-
}
14-
val result =
15-
when {
16-
row < 0 || col < 0 -> Int.MAX_VALUE
17-
row == 0 && col == 0 -> grid[0][0]
18-
else ->
19-
grid[row][col] +
20-
minOf(minPathSumRecursive(grid, row - 1, col), minPathSumRecursive(grid, row, col - 1))
21-
}
22-
return cache.merge(row to col, result, ::maxOf)!!
23-
}
24-
25-
fun minPathSumDp(grid: Array<IntArray>): Int {
4+
/** [64. Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) */
5+
fun minPathSumBottomUp(grid: Array<IntArray>): Int {
266
if (grid.isEmpty()) {
277
return 0
288
}
@@ -44,3 +24,23 @@ fun minPathSumDp(grid: Array<IntArray>): Int {
4424
}
4525
return table[rows][cols]
4626
}
27+
28+
fun minPathSumTopDown(
29+
grid: Array<IntArray>,
30+
row: Int = grid.lastIndex,
31+
col: Int = grid[0].lastIndex,
32+
memo: MutableMap<Pair<Int, Int>, Int> = mutableMapOf(),
33+
): Int {
34+
memo[row to col]?.let {
35+
return it
36+
}
37+
val result =
38+
when {
39+
row < 0 || col < 0 -> Int.MAX_VALUE
40+
row == 0 && col == 0 -> grid[0][0]
41+
else ->
42+
grid[row][col] +
43+
minOf(minPathSumTopDown(grid, row - 1, col), minPathSumTopDown(grid, row, col - 1))
44+
}
45+
return memo.merge(row to col, result, ::maxOf)!!
46+
}

ds-algo/src/main/kotlin/leetcode/dp/Triangle.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package leetcode.dp
22

3-
/** https://leetcode.com/problems/triangle/ Find min path from bottom to top in a triangle. */
3+
/** [120. Triangle](https://leetcode.com/problems/triangle/) */
44
fun minimumTotal(triangle: List<List<Int>>): Int {
5-
val table = IntArray(triangle.size + 1)
6-
7-
for (row in triangle.lastIndex downTo 0) {
5+
val table = triangle.last().toIntArray()
6+
// ! Calculating from triangle bottom to top.
7+
// ! It can be solved from top to bottom also, but need to tackle edge cases 0th and last col
8+
for (row in triangle.lastIndex - 1 downTo 0) {
89
for (col in 0..row) {
10+
// ! Climb from min of prev `col` or `col + 1`, add current cost
911
table[col] = minOf(table[col], table[col + 1]) + triangle[row][col]
1012
}
1113
}

ds-algo/src/main/kotlin/leetcode/dp/UniquePaths.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package leetcode.dp
33

44
fun uniquePaths1d(m: Int, n: Int): Int {
55
val table = IntArray(n) { 1 }
6-
76
repeat(m) {
87
for (col in 1 until n) {
98
table[col] += table[col - 1]

ds-algo/src/main/kotlin/leetcode/dp/UniquePathsWithObstacles.kt renamed to ds-algo/src/main/kotlin/leetcode/dp/UniquePaths2.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package leetcode.dp
44
/** [63. Unique Paths II](https://leetcode.com/problems/unique-paths-ii/) */
55
fun uniquePathsWithObstacles1d(obstacleGrid: Array<IntArray>): Int {
66
val dp = IntArray(obstacleGrid.first().size)
7-
dp[0] = 1
7+
dp[0] = if (obstacleGrid[0][0] != 1) 1 else return 0
88
for (row in obstacleGrid.indices) {
99
for (col in obstacleGrid.first().indices) {
1010
// ! `table[row - 1][col]` is just borrowing from same col data from previous row.
@@ -30,7 +30,6 @@ fun uniquePathsWithObstacles2d(obstacleGrid: Array<IntArray>): Int {
3030
for (col in 1 until cols) {
3131
table[0][col] = if (obstacleGrid[0][col] == 1) 0 else table[0][col - 1]
3232
}
33-
3433
for (row in 1 until rows) {
3534
for (col in 1 until cols) {
3635
if (obstacleGrid[row][col] != 1) {

ds-algo/src/test/kotlin/leetcode/dp/MinimumPathSumTest.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import io.kotest.matchers.shouldBe
66
class MinimumPathSumTest :
77
StringSpec({
88
"minPathSumRecursive" {
9-
minPathSumRecursive(
9+
minPathSumTopDown(
1010
arrayOf(intArrayOf(1, 3, 1), intArrayOf(1, 5, 1), intArrayOf(4, 2, 1))
1111
) shouldBe 7
1212
}
1313

1414
"minPathSumDp" {
15-
minPathSumDp(arrayOf(intArrayOf(1, 3, 1), intArrayOf(1, 5, 1), intArrayOf(4, 2, 1))) shouldBe
16-
7
15+
minPathSumBottomUp(
16+
arrayOf(intArrayOf(1, 3, 1), intArrayOf(1, 5, 1), intArrayOf(4, 2, 1))
17+
) shouldBe 7
1718
}
1819
})

0 commit comments

Comments
 (0)