From 4b8f590eecb19e04298956c59222f828e036ab9a Mon Sep 17 00:00:00 2001 From: gameloader Date: Fri, 26 Apr 2024 11:27:02 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 699bd29..c5a66d5 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -4421,3 +4421,74 @@ func longestIdealString(s string, k int) int { return int(slices.Max(lengths)) } ``` + +## day59 2024-04-26 + +### 1289. Minimum Falling Path Sum II + +Given an n x n integer matrix grid, return the minimum sum of a falling path with non-zero shifts. + +A falling path with non-zero shifts is a choice of exactly one element from each row of grid such that no two elements chosen in adjacent rows are in the same column. + +![0426SCtPSD8Jui7k](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0426SCtPSD8Jui7k.png) + +### 题解 + +本题为一道难题, 拿到题目首先观察, 可以想到的比较直接的点是如果从第一行直接向下一行行遍历并选择的话, 那么以3\*3的矩阵为例, 第一行的第一二列同时选择第二行的第三列, 则对二者来说, 第三行的可选项是相同的. 即除一二列以外的列二者可以选择来累加的元素是相同的. 如第一个示例中的1-6-7,1-6-8,2-6-7,2-6-8. 显然这里对于1,2来说二三列的选择完全相同, 在这种情况下无疑选择1可以得到更小的和. 问题就变成了, 如何把这种已知的对以前的行中的元素的相对大小这一信息保留下来, 很简单, 让每一行的各个元素都保存在其上面行的最小元素和即可. 这样就保证了在能选择该元素的情况下, 以前的路径是从每行中挑出来的可选元素中的最小元素组成的路径. 也就保留了之前各行的元素之间已经判断过的相对大小. 这是一种动态规划的思想, 这里还要解决另外一个问题, 已知n-1行中保留了之前行的最小路径和, 对于第n行的各个元素, 如何高效的从n-1行中的可选元素中选出最小的(同一列的不可选). 显然每个都对n-1行整行做比较是$n^2$的复杂度, 应该高效利用保留信息. 仔细思考一下可以发现, 其实只需要知道最小的和第二小两个值就够了, 因为对于任意一个元素其同一列要么是最小的那个, 那就应该选第二小的, 要么不是最小的, 那就选最小的, 对于求最小值来说, 只需考虑这两种情况就够了(求最小和第二小的值本身也是一个很有趣的小问题, 不用排序, 一次遍历即可, 读者可先自行思考, 然后参考代码中的实现). 思路清晰后, 实现代码即可. + +### 代码 + +```go +func minFallingPathSum(grid [][]int) int { + rowlen := len(grid) + if rowlen == 1{ + return grid[0][0] + } + sums := [][]int{} + firstrow := grid[0] + sums = append(sums, firstrow) + // grid[i][j] <= 99 + small, second, newsmall, newsecond := math.MaxInt32,math.MaxInt32,math.MaxInt32,math.MaxInt32 + for _, value := range firstrow{ + if value < small{ + second = small + small = value + }else if value < second{ + second = value + } + } + for index, row := range grid[1:]{ + rowsum := []int{} + newsmall, newsecond = math.MaxInt32, math.MaxInt32 + for col, value := range row{ + if sums[index][col] != small{ + thissum := small + value + rowsum = append(rowsum, thissum) + if thissum < newsmall{ + newsecond = newsmall + newsmall = thissum + }else if thissum < newsecond{ + newsecond = thissum + } + }else{ + thissum := second + value + rowsum = append(rowsum, thissum) + if thissum < newsmall{ + newsecond = newsmall + newsmall = thissum + }else if thissum < newsecond{ + newsecond = thissum + } + } + } + sums = append(sums, rowsum) + small = newsmall + second = newsecond + } + return small +} +``` + +### 总结 + +Beats 100%