每日一題:Leetcode 面試題47. 禮物的最大價值

題目描述:

在一個 m*n 的棋盤的每一格都放有一個禮物,每個禮物都有一定的價值(價值大於 0)。你可以從棋盤的左上角開始拿格子裏的禮物,並每次向右或者向下移動一格、直到到達棋盤的右下角。給定一個棋盤及其上面的禮物的價值,請計算你最多能拿到多少價值的禮物?

示例 1:

輸入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
輸出: 12
解釋: 路徑 1→3→5→2→1 可以拿到最多價值的禮物

提示:

0 < grid.length <= 200
0 < grid[0].length <= 200

題解:

題目難度:中等

解題思路

最近有同學反應我之前的題解都太簡單了,笑話我水平菜,我一想確實是這樣。今天開始我們就逐步從簡單題過渡到中等題。

本題目是一道典型的動態規劃入門題。

關於動態規劃題目的解題思路,我們首先要明確“狀態”的概念,並且推得“狀態轉移方程”,從而能夠將“小區域的最優狀態”一步步地推得“目標區域的最優狀態”。

大部分沒有接觸過動態規劃的同學,對於本題的解題思路可能會分爲以下幾種:

  1. 暴力求解法:設二維數組的長度爲m,高度爲n,則從左上角走到右下角的方式有m*(n-1)種,我們遍歷這個二維數組的m*(n-1)種走法,求得所有走法中的最大值即可。
  2. 貪心法:走每一步時,我們都面臨着向下走還是向右走的選擇。我們不如每一步都貪心,選擇這兩種選擇中禮物值較大的一種。

(也有同學可能會想到DFS來求解,其實深搜和暴力算法本質上是一樣的,而且濫用遞歸會造成非常大的空間開支,爆棧的風險比較大。)

顯而易見,這幾種方法的侷限性都比較大。暴力求解法存在的最大問題在於“重複計算”,即浪費了很多時間在求解已經算過的狀態值上(這句不理解可以參考北大郭煒老師的mooc),從而超時。而貪心法顯然只考慮到了局部的最優,而忽視了全局最優,俗稱“顧首不顧尾”。

那麼,動態規劃的解法是什麼樣的呢?讓我們從思路一步步做起。

  1. 確定狀態:本題目中,我們可以把“在當前所處的位置所能擁有的最大禮物價值”作爲狀態值。題目中讓我們求的,即是在右下角處的位置所能擁有的最大禮物價值。我們不難求得,在左上角的最大禮物價值就是數組左上角的數據值。(res[0][0] = grid[0][0])而第一行和第一列位置對應的最大禮物價值,也顯然是從左上角到它們位置的累加和。
  2. 確定了狀態之後,我們就需要推出狀態轉移方程來從已知的最大禮物價值推得未知的禮物價值了。我們不妨考慮一下,比如在位置[3,2]的時候,這個位置所對應的最大價值可以怎麼表示呢?換句話說,它是由[3,1]走過來的呢,還是由[2,2]走過來的呢?顯然,當前位置的最大禮物值對應着兩者中的較大者+當前位置的禮物值。
    (dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]) + grid[i][j])

確定了基本思路之後,我們便能夠輕鬆地寫出以下代碼。

AC代碼:

//本函數用於求解右下角位置對應的最大禮物值。
func maxValue(grid [][]int) int {
	dp := make([][]int, len(grid)+1)
	for i := 0; i < len(dp); i ++{
		dp[i] = make([]int, len(grid[0])+1)
	} //構造長寬和數組grid一樣的二維數組dp,用於存儲每個位置對應的最大禮物值。
	dp[0][0] = grid[0][0] //顯然,在左上角處的最大禮物值,就是左上角的禮物值本身。
	for i := 0; i < len(grid); i ++ {
		for j:=0; j<len(grid[0]);j++{
		//根據狀態轉移方程,我們不難得出,每一個位置對應的最優狀態,都可以由其較大的上一步最優狀態值加此位置之值計算出來。
			if dp[i][j+1] > dp[i+1][j]{
				dp[i+1][j+1] = dp[i][j+1] + grid[i][j]
			} else {
				dp[i+1][j+1] = dp[i+1][j] + grid[i][j]
			}
			//這裏不得不吐槽Go語言連個max()函數都沒有,害得廣大羣衆不得不自己判斷大小。
		}
	}
	return dp[len(dp)-1][len(dp[0])-1]//dp數組的右下角對應的最優狀態值即爲所求之值。
}

在這裏插入圖片描述

關於本題目的單元測試環節,歡迎大家移步:GO語言從入門到入土(3):單元測試
原題目鏈接:https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/submissions/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章