力扣64 最小路徑和

2022-03-26 11:17:27 字數 2063 閱讀 5117

給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。

說明:每次只能向下或者向右移動一步。

示例:

輸入:

[ [1,3,1],

[1,5,1],

[4,2,1]

]輸出: 7

解釋: 因為路徑 1→3→1→1→1 的總和最小。

我一開始的想法是正向思路,從起點開始,每個點都有兩種後續走法——向下或者向右,當然其中需要判斷是否可以向下或者向右以及到達終點就停止。我想到的優化是當走到終點後,將當前走過的路徑和記錄下來,找出最小值,別的路徑上在走的時候,如果比當前最小和大,就沒必要繼續了。

來看看我的**:

class solution 

public void dfs(int x, int y, long sum)

// 是否到達終點

if (x == map.length - 1 && y == map[x].length - 1)

return;

}// 是否可以向右

if (y < map[x].length - 1)

// 是否可以向下

if (x < map.length - 1) }}

感覺很理想,然而現實是超時了,確實效率不高,除了第一列和第一行的點,其他點都有可能存在重複計算的可能。

既然正向不行,那咋們就逆向,從終點出發,以終點為起點,計算當前點到終點的最小值,最後推算出到達起點的最小值(這也是我看了別人的解法才知道的,看來自己的思路果然有問題)。這樣就能保證每個點只計算一次,時間效率就是o(m * n),看起來就高效多了。

接下來看看**:

class solution 

// 如果沒有右節點

if (j == grid[i].length - 1)

// 如果沒有下節點

if (i == grid.length - 1)

// 如果下節點和右節點都有的話,則加上其中較小的那個

grid[i][j] += grid[i + 1][j] < grid[i][j + 1] ? grid[i + 1][j] : grid[i][j + 1];}}

return grid[0][0];}}

ok,通過了,執行用時:3ms,記憶體消耗:39.5mb

核心思想就是:

從終點出發,每個點到終點的最小值 = 每個點當前的值 + min(該點下乙個點值, 該點右乙個點)。

你想想,是否是如此呢?

既然知道了反向思路,我們可以優化一下我們之前的正向思路解法。

之前的超時,是因為每個點可能會被計算多次,那麼我們如果計算出,從起點出發,到每個節點的最小值,最終計算到終點,也應該是終點的最小值,你想想是不是這樣呢?

來看看**

class solution 

// 如果沒有左節點

if (j == 0)

// 如果沒有上節點

if (i == 0)

// 如果左節點和上節點都存在,就加上其中最小的值

grid[i][j] += (grid[i][j - 1] < grid[i - 1][j] ? grid[i][j - 1] : grid[i - 1][j]);}}

return grid[row - 1][col - 1];}}

ok,也通過了,執行用時:3ms,記憶體消耗:42.4mb

以上就是這道題目我的解答過程了,不知道大家是否理解了。演算法本來就是就是在做優化,如何能比之前更好更合適,就是優化了。希望能與大家共同進步。

力扣64 最小路徑和

給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。說明 每次只能向下或者向右移動一步。示例 輸入 1,3,1 1,5,1 4,2,1 輸出 7 解釋 因為路徑 1 3 1 1 1 的總和最小 這是一道典型的動態規劃題 dp i j 表示從起點到達...

64 最小路徑和 力扣(LeetCode)

給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。說明 每次只能向下或者向右移動一步。示例 輸入 1,3,1 1,5,1 4,2,1 輸出 7 解釋 因為路徑 1 3 1 1 1 的總和最小。同 不同路徑 一題思路相同,採用動態規劃,動態轉換方程...

64 最小路徑和

給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。說明 每次只能向下或者向右移動一步。示例 輸入 1,3,1 1,5,1 4,2,1 輸出 7 解釋 因為路徑 1 3 1 1 1 的總和最小。用動態規劃可直接解決,dp i j 代表著從 0 0 ...