Given a square array of integers A, we want the minimum sum of a falling path through A.
A falling path starts at any element in the first row, and chooses one element from each row. The next row's choice must be in a column that is different from the previous row's column by at most one.
Example 1:
Input: [[1,2,3],[4,5,6],[7,8,9]]
Output: 12
Explanation:
The possible falling paths are:
- `[1,4,7], [1,4,8], [1,5,7], [1,5,8], [1,5,9]`
- `[2,4,7], [2,4,8], [2,5,7], [2,5,8], [2,5,9], [2,6,8], [2,6,9]`
- `[3,5,7], [3,5,8], [3,5,9], [3,6,8], [3,6,9]`
The falling path with the smallest sum is [1,4,7], so the answer is 12.
Note:
1 <= A.length == A[0].length <= 100-100 <= A[i][j] <= 100
這道題給了一個長寬相等的二維數組,說是讓找一個列路徑,使得相鄰兩個位置的數的距離不超過1,可以通過觀察題目中給的例子來理解題意。由於每個位置上的累加值是由上一行的三個位置中較小的那個決定的,所以這就是一道典型的動態規划 Dynamic Programming 的題,為了節省空間,直接用數組A本身當作 dp 數組,其中 A[i][j] 就表示最后一個位置在 (i, j) 的最小的下降路徑,則最終只要在最后一行中找最小值就是所求。由於要看上一行的值,所以要從第二行開始遍歷,那么首先判斷一下數組是否只有一行,是的話直接返回那個唯一的數字即可。否則從第二行開始遍歷,一定存在的是 A[i-1][j] 這個數字,而它周圍的兩個數字需要判斷一下,存在的話才進行比較取較小值,將最終的最小值加到當前的 A[i][j] 上即可。為了避免重新開一個 for 循環,判斷一下,若當前是最后一行,則更新結果 res,參見代碼如下:
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& A) {
if (A.size() == 1) return A[0][0];
int n = A.size(), res = INT_MAX;
for (int i = 1; i < n; ++i) {
for (int j = 0; j < n; ++j) {
int pre = A[i - 1][j];
if (j > 0) pre = min(pre, A[i - 1][j - 1]);
if (j < n - 1) pre = min(pre, A[i - 1][j + 1]);
A[i][j] += pre;
if (i == n - 1) res = min(res, A[i][j]);
}
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/931
類似題目:
Minimum Falling Path Sum II
參考資料:
https://leetcode.com/problems/minimum-falling-path-sum/
https://leetcode.com/problems/minimum-falling-path-sum/discuss/186666/C%2B%2BJava-4-lines-DP
