團滅 LeetCode 打家劫舍 問題

2022-07-12 01:51:13 字數 2308 閱讀 9367

leetcode 「打家劫舍」系列問題共有三道:

198.打家劫舍

213.打家劫舍ii

337.打家劫舍iii

int rob(vector& nums);

建模:給定陣列 nums中都是正整數,nums中相鄰的數不能同時取,制定一種取數策略,

使得取到的nums中的數和最大,返回取到的數的最大和。

思路:題目很容易理解,而且動態規劃的特徵很明顯。解決動態規劃問題的關鍵就是找「狀態」和「選擇」。

1. 定義狀態:定義dp[i] 表示 陣列 nums[0:i]取數返回的最大和;

2. 狀態轉移: 根據數學歸納的方法, 求狀態轉移方程就是  假設 dp[0,1,2,...,i-1]都已知 求dp[i] 。

若 取 nums[i]  就不能取 nums[i-1],dp[i] = nums[i] + dp[i-2]  ;若不取 nums[i]  ,則 nums[i-1] 可以取

也可以不取,dp[i] = dp[i-1],dp[i] 取兩種選擇的最大值。最終的狀態轉移方程為:

dp[i] = max(dp[i-1],dp[i-2]+nums[i])

狀態轉移方程中 有dp[i] ,dp[i-1]  ,dp[i-2],為了保證陣列的下標從0開始,i 應從 2 開始,dp[0],dp[1],應該作為

base case 在狀態轉移之前處理好。因為只涉及到相鄰 3 個狀態,所以 可以將狀態陣列空間壓縮,使用

兩個變數 front ,before_front 記錄狀態。

**如下:

1

int rob(vector&nums)214

return

front;

15 }

這題和第一題 唯一的不同是nums由普通陣列變成了環陣列,即  nums[n-1 ] 和 nums[0] 也是相鄰的,

在選擇是否取  nums[n-1] 時,需要考慮到 nums[n-2] 和nums[0] 都是相鄰的,選擇nums 中的其他元素 和

1

int rob(vector&nums)213

14int rob_helper(vector& nums,int low,int

high)

1528

return

front;

29 }

第一題的房子排列是 乙個普通的陣列,要求不能取相鄰的房子內的錢。第二題的房子排列成乙個環形陣列,

首尾相接,要求不能取相鄰的房子內的錢。第三題的房子分布在一顆二叉樹上的節點上,要求不能取相鄰的房子內的錢。

方法一:備忘錄 + 遞迴 

思路分析:二叉樹問題,顯然可以用遞迴解決。根據題意,對二叉樹的根節點:

1. 如果不取根節點的房子的錢,則作為根節點的相鄰節點,根的左節點和根的右節點 都可以取 可以不取,遞迴地計算

左子樹和右子樹,然後相加就可以了。

2. 如果取根節點的房子的錢,則根的左節點和根的右節點 都不能取了,遞迴地計算根節點的左節點的左子樹、根節點的

左節點的右子樹、根節點的右節點的左子樹、根節點的右節點的右子樹,將 4 個遞迴計算得到的結果再加上 root->val 就是

取根節點的房子的錢 這種選擇的結果。

3. 在1,2 兩個結果中取最大值即得到最終的結果。

注:在遞迴計算的過程中,計算得到的子樹的結果存到備忘錄中,避免重複計算,提高效率。

**如下:

1

class

solution

18 }

方法二: 更高效漂亮的遞迴

1

introb(treenode root) 56

/*返回乙個大小為 2 的陣列 arr

7arr[0] 表示不搶 root 的話,得到的最大錢數

8arr[1] 表示搶 root 的話,得到的最大錢數 */9

int dp(treenode root) ;

12int left =dp(root.left);

13int right =dp(root.right);

14//

搶,下家就不能搶了

15int rob = root.val + left[0] + right[0

];16

//不搶,下家可搶可不搶,取決於收益大小

17int not_rob = math.max(left[0], left[1

])18 + math.max(right[0], right[1

]);19

20return

newint

;21 }

團滅 LeetCode 打家劫舍問題

有讀者私下問我 leetcode 打家劫舍 系列問題 英文版叫 house robber 怎麼做,我發現這一系列題目的點讚非常之高,是比較有代表性和技巧性的動態規劃題目,今天就來聊聊這道題目。打家劫舍系列總共有三道,難度設計非常合理,層層遞進。第一道是比較標準的動態規劃問題,而第二道融入了環形陣列的...

團滅LeetCode關於回文串的演算法題

本文主要針對leetcode上關於回文字串的演算法題進行總結。總體而言,leetcode上關於回文字串的演算法題可以分為以下幾類 1 在已知的字串串找到最長的回文字串 2 修改現有的字串得到回文字串 3 分割現有的字串得到回文字串 涉及題目 5.最長回文子串 131.分割回文串 132.分割回文串 ...

LeetCode 打家劫舍

你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。示例 1 輸入 1...