Day41:198.打家劫舍、213.打家劫舍II、337.打家劫舍 III

文章目錄

    • 198.打家劫舍
      • 思路
      • 代碼實現
    • 213.打家劫舍II
      • 思路
      • 代碼實現
    • 337.打家劫舍 III
      • 思路
      • 代碼實現
      • 記憶化遞歸法(其他解法)


198.打家劫舍

題目鏈接

思路

  1. 確定dp數組(dp table)以及下標的含義
    dp[i]:考慮下標i以內的房屋,最多可以偷竊的金額為dp[i]。
    注意:dp[i]不是一定要偷第i個房間,它代表的是從0-i的范圍房間內能偷的最大值。
  2. 確定遞推公式
    決定dp[i]的條件有第i房間偷還是不偷。
    如果偷第i房間,那么dp[i] = dp[i - 2] + nums[i]
    如果不偷第i房間,那么dp[i] = dp[i - 1],即考慮 i-1房
    然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
  3. dp數組如何初始化
    從遞推公式dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])可以看出,遞推公式的基礎就是dp[0] 和 dp[1]。從dp[i]的定義上來講,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);
    vector dp(nums.size());
    dp[0] = nums[0];
    dp[1] = max(nums[0], nums[1]);
  4. 確定遍歷順序
    dp[i] 是根據dp[i - 2] 和 dp[i - 1] 推導出來的,那么一定是從前到后遍歷
  5. 舉例推導dp數組

代碼實現

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

213.打家劫舍II

題目鏈接

思路

這道題和上一道題幾乎是一模一樣,只不過是圍成一個圈,那么這道題最重要的點就是,怎么避免偷的房間首尾相連
所以重點就是不讓他們首尾相連,那么可以分情況討論:

  1. 不考慮首尾
  2. 考慮首不考慮尾
  3. 不考慮首考慮尾

而第一種情況包含在2和3情況里,直接討論2和3情況即可,這樣一個環形數組又變成了線型數組,和打家劫舍一模一樣。

代碼實現

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

337.打家劫舍 III

題目鏈接

思路

這道題比上面那道題又加了一個檔次,是二叉樹和動態規劃的結合運用,第一次見我也是一臉懵逼。這道題用遞歸結構分析:

  1. 確定遞歸函數的參數和返回值
    這里我們要求一個節點偷與不偷的兩個狀態所得到的金錢,那么返回值就是一個長度為2的數組。dp數組以及下標的含義:下標為0記錄不偷該節點所得到的的最大金錢,下標為1記錄偷該節點所得到的的最大金錢。
  2. 確定終止條件
    在遍歷的過程中,如果遇到空節點的話,很明顯,無論偷還是不偷都是0,所以就返回{0,0}。這也相當于dp數組的初始化
  3. 確定遍歷順序
    首先明確的是使用后序遍歷。 因為要通過遞歸函數的返回值來做下一步計算。
  4. 確定單層遞歸的邏輯
    如果是偷當前節點,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0];
    如果不偷當前節點,那么左右孩子就可以偷,至于到底偷不偷一定是選一個最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);
    最后當前節點的狀態就是{val2, val1};

代碼實現

class Solution {
public:vector<int> robTree(TreeNode* root){if(root==nullptr)return {0,0};//dp[0]為當前未偷,dp[1]為當前偷了vector<int> left=robTree(root->left);vector<int> right=robTree(root->right);int val1=max(left[1],left[0])+max(right[0],right[1]);int val2=root->val+left[0]+right[0];return {val1,val2};}int rob(TreeNode* root) {vector<int> result=robTree(root);return max(result[0],result[1]);}
};

記憶化遞歸法(其他解法)

可以使用一個map把計算過的結果保存一下,這樣如果計算過孫子了,那么計算孩子的時候可以復用孫子節點的結果。
代碼如下:

class Solution {
public:unordered_map<TreeNode* , int> umap; // 記錄計算過的結果int rob(TreeNode* root) {if (root == NULL) return 0;if (root->left == NULL && root->right == NULL) return root->val;if (umap[root]) return umap[root]; // 如果umap里已經有記錄則直接返回// 偷父節點int val1 = root->val;if (root->left) val1 += rob(root->left->left) + rob(root->left->right); // 跳過root->leftif (root->right) val1 += rob(root->right->left) + rob(root->right->right); // 跳過root->right// 不偷父節點int val2 = rob(root->left) + rob(root->right); // 考慮root的左右孩子umap[root] = max(val1, val2); // umap記錄一下結果return max(val1, val2);}
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167391.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167391.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167391.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華清遠見嵌入式學習——網絡編程——小項目

項目要求&#xff1a; 代碼實現&#xff1a; 服務器端&#xff1a; #include <myhead.h>//定義協議包 struct proto {char type;char name[20];char text[128]; };int main(int argc, const char *argv[]) {//判斷從終端輸入的字符串的個數if(argc ! 3){printf("…

mysql中TIMESTAMP 和DATETIME數據類型的區別

在MySQL中&#xff0c;TIMESTAMP和DATETIME都用于表示日期和時間&#xff0c;但是它們之間存在一些關鍵區別。下面我們通過幾個關鍵點來詳細了解這兩種數據類型的使用&#xff1a; 存儲范圍 TIMESTAMP類型的存儲范圍從1970-01-01 00:00:01 UTC到2038-01-19 03:14:07 UTC。DAT…

Django之importlib模塊

【1】介紹 import importlib importlib模塊是Python中用于動態加載和導入模塊的內置模塊 它提供了一組函數和類&#xff0c;使得我們可以在運行時根據需要加載模塊&#xff0c;并且可以對已導入的模塊進行操作和管理 【2】importlib模塊中的import_module方法 【2.1】導入模塊…

無需API開發,錢方QFPay連接營銷系統和廣告推廣平臺

隨著電子商務市場的不斷發展&#xff0c;企業需要集成各種業務系統&#xff0c;以提高業務效率和降低運營成本。錢方QFPay提供了一種創新的解決方案&#xff0c;幫助企業實現系統間的連接和集成&#xff0c;無需進行復雜的API開發。除了電商系統和客服系統&#xff0c;錢方還能…

武漢光庭公司地圖引擎開發工程師24秋招三場面試完整流程

本文介紹2024屆秋招中&#xff0c;武漢光庭信息技術股份有限公司的智能駕駛地圖引擎開發工程師崗位一面、二面、三面的面試基本情況、提問問題等。 10月投遞了武漢光庭信息技術股份有限公司的智能駕駛地圖引擎開發工程師崗位&#xff0c;暫時并不清楚所在的部門。目前完成了全部…

mysql:修改密碼的幾種方式

背景 當我們 brew install mysql 新安裝 mysql 的時候&#xff0c;是沒有密碼的&#xff0c;我們可以直接通過 mysql -u root 連接上。但是密碼還是要設置的&#xff0c;一是為了安全&#xff0c;二是有些數據庫軟件如 Sequel 連接都是必須要密碼的&#xff0c;接下來我們來看…

電磁建模的分布式并行計算技術

本文提出了一種新的分布式并行電磁建模技術&#xff0c;以加快電磁結構的神經網絡建模過程。現有的電磁建模技術通常需要反復改變微波器件的參數&#xff0c;驅動電磁模擬器以獲得足夠的訓練和測試樣本。隨著電磁建模問題復雜性的增加&#xff0c;由于單臺計算機的性能有限&…

DP好題總結

LCIS最長公共上升子序列 題解&#xff1a;https://blog.csdn.net/weixin_50624971/article/details/116892236 概括&#xff1a; 決策優化DP 考慮LCS可以寫成 O ( n 4 ) O(n^4) O(n4) 的如果我們把狀態設為 f [ i , j ] f[i,j] f[i,j] 表示考慮到 a [ i ] , b [ j ] a[i]…

機器學習【00】pycharm使用遠程服務器

我們使用conda在服務器上創建虛擬環境&#xff0c;遠程使用pycharm進行編程 pycharm版本2023.1.3 一.首先在服務器上創建虛擬環境 注&#xff1a;anaconda的安裝可以參考ubuntu系統miniconda的安裝 conda create --name tac python3.7二.pycharm 連接 點擊add interpreter …

查企業聯系電話的方法

對于銷售來說&#xff0c;獲取準確、全面的企業聯系方式&#xff0c;無疑是開發客戶的基礎與保障&#xff0c;因為任憑能力再高&#xff0c;說服能力多強&#xff0c;沒有與客戶接觸的機會&#xff0c;這些都是無稽之談。但是大家都知道&#xff0c;道理都懂&#xff0c;但是要…

.yaml文件的簡介

文章目錄 YAML文件簡介YAML文件的示例 YAML文件簡介 YAML是一種人類可讀的數據序列化標準。它常被用于配置文件、數據交換格式、以及在一些編程語言中的數據結構描述。 YAML 文件的主要特點有如下四點&#xff1a; 可讀性&#xff1a;YAML 的語法結構簡潔明了&#xff0c;容…

報錯AttributeError: module ‘cv2‘ has no attribute ‘ximgproc‘

報錯AttributeError: module ‘cv2’ has no attribute ‘ximgproc’ 首先查看是否安裝opencv-contrib-python pip list | grep opencv顯示 opencv-contrib-python 4.4.0.46 opencv-python 4.8.1.78 opencv-pyt…

【2023.11.24】Mybatis基本連接語法學習?

基本配置 1.如果使用Maven管理項目&#xff0c;需要在pom.xml中配置依賴。 2.安裝Mybatis-3.5.7.jar包 3.進行XML配置&#xff1a;這里將文件命名為mybatis-config.xml 配置數據庫連接XML文件 <?xml version"1.0" encoding"UTF-8" ?> <!DO…

Crypto(10)BUUCTF-RSA3(共模攻擊)

一.共模攻擊的現實意義 好奇一個問題&#xff0c;即共模攻擊有什么現實意義&#xff1f; 發現也沒有什么現實意義&#xff0c;因為&#xff08;n,e&#xff09;是已知的&#xff0c;通常每個用戶的n是不同的&#xff0c;除非特殊情況吧 二.共模攻擊的數學原理&#xff1a; 通…

最重要的BI測試-適用于任何BI和分析平臺

為什么 BI 測試是答案 相信你的數據可視化是成功執行商業智能 (BI) 和分析項目的關鍵因素。我敢肯定&#xff0c;你遇到過以下情況&#xff1a;業務主管或業務用戶反饋說他們的分析看起來不對&#xff0c;他們的 KPI 看起來有問題&#xff0c;或者速度太慢而無法使用。要問自己…

SQL 通配符:用于模糊搜索和匹配的 SQL 關鍵技巧

SQL通配符字符 通配符字符用于替代字符串中的一個或多個字符。通配符字符與LIKE運算符一起使用。LIKE運算符用于在WHERE子句中搜索列中的指定模式。 示例 返回所有以字母 ‘a’ 開頭的客戶&#xff1a; SELECT * FROM Customers WHERE CustomerName LIKE a%;通配符字符 符…

5:kotlin 類(Classes )

kotlin支持面向對象編程&#xff0c;也有雷和對象的概念 要聲明一個類需要使用class關鍵字 class Customer屬性&#xff08;Properties&#xfeff;&#xff09; 可以在類名后邊添加()&#xff0c;在()里邊聲明屬性 class Contact(val id: Int, var email: String)聲明了不…

單片機、ARM、嵌入式開發、Android 底層開發有什么關系?

單片機、ARM、嵌入式開發、Android 底層開發有什么關系&#xff1f; 從我目前的見識來看&#xff1a; 單片機是個系統&#xff08;比如&#xff1a;51、AVR、PLC...&#xff09;&#xff0c;其中包含了去除了輸入輸出之外的運算器、控制器、存儲器&#xff0c;我們用程序可以非…

從Redis反序列化UserDetails對象異常后發現FastJson序列化的一些問題

最近在使用SpringSecurityJWT實現認證授權的時候&#xff0c;出現Redis在反序列化userDetails的異常。通過實踐發現&#xff0c;使用不同的序列化方法和不同的fastJson版本&#xff0c;異常信息各不相同。所以特地記錄了下來。 一、項目代碼 先來看看我項目中redis相關配置信息…

黑馬點評筆記 redis緩存三大問題解決

文章目錄 緩存問題緩存穿透問題的解決思路編碼解決商品查詢的緩存穿透問題 緩存雪崩問題及解決思路緩存擊穿問題及解決思路問題分析使用鎖來解決代碼實現 邏輯過期方案代碼實現 緩存問題 我們熟知的是用到緩存就會遇到緩存三大問題&#xff1a; 緩存穿透緩存擊穿緩存雪崩 接…