日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

打家劫舍系列(dp)

發布時間:2025/3/21 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 打家劫舍系列(dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

打家劫舍類的題目是動態規劃里的經典題目,有很多種變換形式,下面就介紹一下力扣里面的所有打家劫舍的題目;

打家劫舍

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

示例 1:輸入:[1,2,3,1]
輸出:4
解釋:偷竊 1 號房屋 (金額 = 1) ,然后偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。

示例 2:
輸入:[2,7,9,3,1]
輸出:12
解釋:偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接著偷竊 5 號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。

提示:
0 <= nums.length <= 100
0 <= nums[i] <= 400

我們來分析一下這道題:
1,dp[i]代表 i 以內的房屋偷盜的最大金額;
2,如果在第 i 間房屋偷錢了,那么dp[i] = dp[i - 2] + nums[i];
如果沒有在第 i 間房屋偷錢,那么dp[i] = dp[i - 1];
因為求最大值,所以dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
3,dp數組初始化無非就兩種情況
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
4,因為dp[i]是由dp[i - 1]和dp[i - 2]求得的,所以可以看出來遍歷順序就是從前到后遍歷的;

代碼如下:

class Solution { public:int rob(vector<int>& nums) {int n = nums.size();if (n == 0) return 0;if (n == 1) return nums[0];vector<int> dp(n);dp[0] = nums[0];dp[1] = max(nums[0], nums[1]);for (int i = 2; i < n; ++i) {dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);}return dp[n - 1];} };

這是打家劫舍1.0基礎版,比較容易求出來,接下來我們來個升級版的;

打家劫舍II

你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都 圍成一圈 ,這意味著第一個房屋和最后一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警 。
給定一個代表每個房屋存放金額的非負整數數組,計算你 在不觸動警報裝置的情況下 ,能夠偷竊到的最高金額。

示例 1:
輸入:nums = [2,3,2]
輸出:3
解釋:你不能先偷竊 1 號房屋(金額 = 2),然后偷竊 3 號房屋(金額 = 2), 因為他們是相鄰的。

示例 2:
輸入:nums = [1,2,3,1]
輸出:4
解釋:你可以先偷竊 1 號房屋(金額 = 1),然后偷竊 3 號房屋(金額 = 3)。偷竊到的最高金額 = 1 + 3 = 4 。

示例 3:
輸入:nums = [0]
輸出:0

提示:
1 <= nums.length <= 100
0 <= nums[i] <= 1000

這道題里的房屋都圍成了一個圈,這樣和第一題不同的就是需要多考慮一下,
情況1:如果偷了第一個房屋,最后一個就不能偷;
情況2:如果沒有偷第一個房屋(那就是從第二個房屋開始偷的),就可以偷最后一個;
可以發現單看哪種情況都是和打家劫舍1.0版本一樣的;
所以我們需要單獨求出兩種情況的最大金額,然后取最大值即可;
為了方便求兩種情況最大金額,再額外寫個函數更好;

代碼如下:

class Solution { public:int rob(vector<int>& nums) {int n =nums.size();if (n == 1) return nums[0];if (n == 2) return max(nums[1], nums[0]);//情況2和情況1return max(robRank(nums, 1, n - 1), robRank(nums, 0, n - 2));}int robRank(vector<int>& nums, int begin, int end) {vector<int> dp(nums.size());dp[begin] = nums[begin];dp[begin + 1] = max(nums[begin], nums[begin + 1]);for (int i = begin + 2; i <= end; ++i) {dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);}return dp[end];} };

這道題就需要多考慮一下了,但是核心還是一樣的;接下來來個不一樣的

打家劫舍III

在上次打劫完一條街道之后和一圈房屋后,小偷又發現了一個新的可行竊的地區。這個地區只有一個入口,我們稱之為“根”。除了“根”之外,每棟房子有且只有一個“父“房子與之相連。一番偵察之后,聰明的小偷意識到“這個地方的所有房屋的排列類似于一棵二叉樹”。如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。

示例1

示例2

這是一道樹形dp的入門題,相似的題目,需要我們熟悉二叉樹的遍歷,而這道題需要用到的是后續遍歷
我們假設 1 為偷, 0 為不偷,那么我們需要一個遞歸函數,返回偷和不偷的金額即可,最后區它倆的最大值就是本題答案;
所以我們可以先確定返回值為一個vector數組,大小為2

vector<int> robTree(TreeNode* root)

那么這個遞歸函數的終止條件又是什么?
當傳入節點 root 為空時,我們就返回{0, 0}就可以了;

if (!root) return vector<int>{0, 0};

接下來我們定義兩個vector變量存放遞歸左子樹和右子樹的結果

vector<int> l = robTree(root -> left); vector<int> r = robTree(root -> right);

最后我們就該確定遞歸邏輯了,這里分為兩種情況
1,如果偷root,則左右孩子就不能偷

int ans1 = root -> val + l[0] + r[0];

2,如果不偷root,那么左右孩子都可以偷,但是偷或者不偷需要在這里選擇一個最大值;

int ans2 = max(l[1], l[0]) + max(r[1], r[0]);

最后返回ans2和ans1就可以了,一定要注意返回時的順序,不偷的在前,偷的在后

代碼如下:

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/ class Solution { public:int rob(TreeNode* root) {vector<int> ans = robTree(root);return max(ans[0], ans[1]);}// 長度為2的數組,0不偷,1偷vector<int> robTree(TreeNode* root) {if (!root) return vector<int>{0, 0};vector<int> l = robTree(root -> left);vector<int> r = robTree(root -> right);int ans1 = root -> val + l[0] + r[0]; //偷rootint ans2 = max(l[1], l[0]) + max(r[1], r[0]); //不偷rootreturn {ans2, ans1};} };

總結

打家劫舍系列就結束了,這里三道題都是力扣原題,最后一道題用到了樹形dp,所以需要多了解一下,前兩道題目都很相似,都可以練練手,有什么問題也歡迎交流;

總結

以上是生活随笔為你收集整理的打家劫舍系列(dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美人一级淫片a免费播放 西方av在线 | 成人动漫久久 | 国产免费一级片 | 国产成人精品av | 少妇一级淫片免费播放 | 永久免费av无码网站性色av | 男生和女生差差视频 | 久久久久无码国产精品一区李宗瑞 | 国产精品毛片一区 | 午夜免费福利在线 | 超碰在线看 | 麻豆视频播放 | 特级特黄刘亦菲aaa级 | 波多野结衣视频免费 | 经典杯子蛋糕日剧在线观看免费 | 空姐吹箫视频大全 | 黄色网址网站 | 天天爽网站| 中文亚洲av片不卡在线观看 | 国产色在线观看 | 国精产品一区 | 亚州av一区 | 毛片av免费| 夫妻自拍偷拍 | 性欧美长视频 | 在线看a网站 | 日韩av在线播 | 黄色在线小视频 | 456亚洲影院 | 97视频成人 | 亚洲天堂三区 | 2021av视频| 华丽的外出在线 | 国产免费叼嘿网站免费 | 日韩国产三级 | 好吊日在线观看 | av白浆| 国产精品免费久久 | 特大黑人巨交吊性xxxxhd | 亚洲精品你懂的 | 搡老熟女老女人一区二区 | 欧美性视频一区二区 | 色吧久久 | 亚洲欧美日本在线观看 | 欧美女人一区二区 | 亚洲av无码国产精品色午夜 | 中文字幕在线官网 | 蜜臀视频一区二区 | 久久老司机精品视频 | 韩国成年人网站 | 黄色片视频在线观看 | www.成人免费视频 | 日本公妇乱偷中文字幕 | 欧美老熟妇喷水 | 久色成人网 | 亚洲一区二区三区在线 | 人妻互换一区二区激情偷拍 | 久草视频在线看 | 美女被草出水 | 蝌蚪自拍网站 | 久久青| 伊人久久五月天 | 日韩第一视频 | 成人福利午夜 | 高清久久 | 久久久久久久久久国产 | 日本高清视频在线播放 | 男女国产精品 | 91资源在线播放 | h网址在线观看 | 七仙女欲春2一级裸体片 | 国产电影一区二区三区爱妃记 | 中日韩在线观看 | 国产一二区在线 | free性娇小hd第一次 | ts人妖另类精品视频系列 | 国产视频一区二区三区在线播放 | 成人动漫在线观看视频 | 无码人妻精品一区二区蜜桃色欲 | 精品自拍偷拍 | 久久综合久色欧美综合狠狠 | 不卡av在线播放 | 亚洲天堂网在线视频 | 天堂网成人 | 香蕉视频免费看 | 色性网 | 国产精品一区二区网站 | 天天干 夜夜操 | 欧美爱爱网站 | 99精品在线播放 | 欧美精品自拍偷拍 | 国产91一区二区三区 | 色欲亚洲Av无码精品天堂 | 男生桶女生肌肌 | 蜜桃在线一区二区 | 视频一区 中文字幕 | 让人下面流水的视频 | 国内自拍真实伦在线观看 | 欧美激情在线免费 |