LeetCodeDiary

A Diary for solving LeetCode problems

View on GitHub

1289. 下降路径最小和 II

给你一个整数方阵 arr ,定义「非零偏移下降路径」为:从 arr 数组中的每一行选择一个数字,且按顺序选出来的数字中,相邻数字不在原数组的同一列。

请你返回非零偏移下降路径数字和的最小值。

示例 1:

输入:arr = [[1,2,3],[4,5,6],[7,8,9]]
输出:13
解释:
所有非零偏移下降路径包括:
[1,5,9], [1,5,7], [1,6,7], [1,6,8],
[2,4,8], [2,4,9], [2,6,7], [2,6,8],
[3,4,8], [3,4,9], [3,5,7], [3,5,9]
下降路径中数字和最小的是 [1,5,7] ,所以答案是 13 。

提示:

动态规划 困难

思路和最短路径差不多,不过每次状态转移遍历查找上一行的最小值这一过程可以优化,时间复杂度可以优化到O(N)

代码

1. O(N)

class Solution:
    def minFallingPathSum(self, arr: List[List[int]]) -> int:
        n = len(arr)
        for i in range(1, n):
            for j in range(n):
                t = min(arr[i-1][:j] + arr[i-1][j+1:])
                arr[i][j] += t
        return min(arr[n-1])

2. 时间优化版

class Solution:
    def minFallingPathSum(self, arr: List[List[int]]) -> int:
        n = len(arr)
        MAX = float('inf')
        j1, j2 = -1, -1 # j1记录最小值坐标, j2记录次小值坐标
        for j in range(n):
            if arr[0][j] < ( MAX if j1 == -1 else arr[0][j1]):
                j2, j1 = j1, j
            elif arr[0][j] < ( MAX if j2 == -1 else arr[0][j2]):
                j2 = j
        j3, j4 = j1, j2
        for i in range(1, n):
            j1, j2 = j3, j4
            j3, j4 = -1, -1
            for j in range(n):
                if j != j1:
                    arr[i][j] += arr[i-1][j1]
                else:
                    arr[i][j] += arr[i-1][j2]
                # 更新本行最小、次小值
                if arr[i][j] < ( MAX if j3 == -1 else arr[i][j3]):
                    j4, j3 = j3, j
                elif arr[i][j] < ( MAX if j4 == -1 else arr[i][j4]):
                    j4 = j
        return min(arr[n-1])