【小白友好】LeetCode 打家劫舍 III

https://leetcode.cn/problems/house-robber-iii/description/

前言

建議還是先看看動態規劃的基礎題再看這個。動態規劃是不刷題,自己100%想不出來的
基礎題:

  • 23

小白想法

現在我們想遍歷的數據結構不是數組了,而是一顆樹。在樹上的dp叫做“樹形dp”(so called)。
那在遍歷尋找解更新dp的時候無非就是用遍歷樹的dfs那一套了,不再是for i in range(length)了。

現在不方便用dp數組去存儲dp的值了,畢竟這是個樹。那用什么?我們之前之所以用數組,是因為使用dp[i]能夠直接取到遍歷到nums[i]時dp的值,之前的dp數組實際上充當的是一個hash table(字典、map…隨便你怎么叫)的作用。 那我們就直接用字典就好啦!不再用數組了。

然后能不能像for i in range(length)一樣“從前往后”邊遍歷邊更新?樹上的“從前往后”是什么?是從葉子走向根

有了前幾點的鋪墊,下面正式進入狀態轉移方程的構建。

還能不能像以前“打家劫舍”那個題一樣通過選擇前幾個狀態來更新dp?
看上去好像可以。但是請注意我們現在的“dp數組”不是數組了,而是一個字典。字典的key是node,value是dp值。如果是數組,我們可以很方便的通過i-1,i-2指針來訪問前面的狀態,但是此時的字典已經不適合了。 當前的狀態i和前面時刻-2的“聯系”已經沒有了。

題外話,莫非我可以先把“樹形”的數據先壓成一個數組,然后再套用之前的思路?想法很好,甚至也能做,但是寫起來比較麻煩,下一個!

就算是有聯系,在當前節點時,需要考慮 自己2個孩子是否被偷,沒偷就有可能跟孫子一起被偷,共計6個節點,我相信寫起來也挺復雜,要max很多次。

dead end after all…

題解,學習

換個dp數組的意義吧!我們不拘泥于過去的思路了。
在之前做“最大連乘子數組”的時候我們不是也用了2個dp數組嗎?

把dp拆開成2個,分成 選擇了子節點的最大值,和沒選擇了子節點的最大值。請注意樹上的“從前往后”是從葉子到根。把這2個dp分別叫做dp_selecteddp_unselected

先考慮最簡單的情況,從最前面開始,只有一個葉子的時候,2個dp的值很好知道,葉子值或者0。

而當到了樹上的分支now的時候,dp_selected[now]的意義是選擇當前節點,那么應該等于自己當前節點的值+沒選自己孩子的最大dp值:now.val+dp_unselected[now.left]+dp_unselected[now.right],只有這 一種情況,是因為相鄰的父子不能一起選;而dp_unselected[now]就比較多了:由于我當前節點沒選擇,那么我的孩子可以選,也可以不選,那我要當前最大的,要取他們的最大值更新。

上面寫的比較“大白話”,我個人感覺用數學公式表達起來比較簡潔易懂。。

以下為官方題解
![在這里插入圖片描述](https://img-blog.csdnimg.cn/direct/8a20184fef244d6a9e5cfdaa0b59ad4c.png

接下來就是遍歷,然后通過轉移方程一邊遍歷一邊更新就行。

代碼

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def rob(self, root: Optional[TreeNode]) -> int:# dp的存儲形式變了,變成字典# dp的意義變了,不再是“以xx結尾的結果”from collections import defaultdictdp_selected,dp_unselected=defaultdict(int),defaultdict(int)def travel_tree(now):if now is None:return travel_tree(now.left)travel_tree(now.right)left=now.leftright=now.rightres1=now.val+dp_unselected[left]+dp_unselected[right]res2=max(dp_selected[left],dp_unselected[left])+max(dp_selected[right],dp_unselected[right])dp_selected[now]=res1# 可以選擇不更新,因為不更新他就是0# 在節點選擇的過程中,0是肯定會被丟棄的dp_unselected[now]=res2return travel_tree(root)return max(dp_selected[root],dp_unselected[root])

defaultdict的作用是給予在dict中不存在的key一個初始值,簡化代碼。

提交,過了。

想不出來,不刷題真的想不出來。

優化

顯然dp的hash table是很重要的,但是我們能不能把他也優化掉,不使用他的額外的空間呢?
我們可以從轉移方程看到,當前點的更新只跟自己孩子的那幾個值有關。

這熟悉的配方!在dp[i]只跟dp[i-1]有關時,我們也能通過類似的方法只保留上一個dp的值來優化空間。

那么怎么只保留上一個dp的值呢?我們上一個dp的值是“選左孩子的最大值”、“不選左孩子的最大值”、“選右孩子的最大值”、“不選右孩子的最大值”,一共4個,使用函數返回給父節點就可以了!(畢竟除了使用額外的空間,函數返回值是唯一父子能交流的東西了)

class Solution:def rob(self, root: Optional[TreeNode]) -> int:def travel_tree(now):if now is None:  return 0, 0  l_rob, l_not_rob = travel_tree(now.left)r_rob, r_not_rob = travel_tree(now.right)rob = l_not_rob + r_not_rob + node.val  # 選not_rob = max(l_rob, l_not_rob) + max(r_rob, r_not_rob)  # 不選return rob, not_robreturn max(travel_tree(root))  # 根節點選或不選的最大值

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

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

相關文章

C++遞推

統計每個月兔子的總數 #include<bits/stdc.h> using namespace std; int n,sum0; void f(int); int main() {int a[1000];cin>>n;a[1]1;a[2]2;for(int i3;i<1000;i){a[i]a[i-1]a[i-2];}cout<<a[n];return 0; } void f(int n){}猴子吃桃子 #include<b…

2024年華為OD機試真題-電腦病毒感染-Python-OD統一考試(C卷)

題目描述: 一個局域網內有很多臺電腦,分別標注為0 - N-1的數字。相連接的電腦距離不一樣,所以感染時間不一樣,感染時間用t表示。 其中網絡內一個電腦被病毒感染,其感染網絡內所有的電腦需要最少需要多長時間。如果最后有電腦不會感染,則返回-1 給定一個數組times表示一個…

在Spring Boot中如何實現異常處理?

在Spring Boot中&#xff0c;異常處理可以通過幾種方式實現&#xff0c;以提高應用程序的健壯性和用戶體驗。這些方法包括使用ControllerAdvice注解、ExceptionHandler注解、實現ErrorController接口等。下面是一些實現Spring Boot異常處理的常用方法&#xff1a; 1. 使用Cont…

Git實戰(2)

git work flow ------------------------------------------------------- ---------------------------------------------------------------- 場景問題及處理 問題1&#xff1a;最近提交了 a,b,c,d記錄&#xff0c;想把b記錄刪掉其他提交記錄保留&#xff1a; git reset …

【C++ 編程指南】

C 編程指南 ■ C環境安裝■ C 基本語法■ 預定義宏■ # 和 ## 運算符■ C 引用■ C 命名空間■ 定義命名空間■ using 指令■ 嵌套的命名空間 ■ String類■ 類■ 類的static靜態成員 ■ C 繼承■ 繼承類型 public、protected 或 private■ 訪問控制和繼承■ 多繼承■ 數據抽象…

機器學習-面經

經歷了2023年的秋招&#xff0c;現在也已經入職半年了&#xff0c;空閑時間將面試中可能遇到的機器學習問題整理了一下&#xff0c;可能答案也會有錯誤的&#xff0c;希望大家能指出&#xff01;另外&#xff0c;不論是實習&#xff0c;還是校招&#xff0c;都祝福大家能夠拿到…

990-28產品經理:Different types of IT risk 不同類型的IT風險

Your IT systems and the information that you hold on them face a wide range of risks. If your business relies on technology for key operations and activities, you need to be aware of the range and nature of those threats. 您的IT系統和您在其中持有的信息面臨…

數據結構c版(2)——二叉樹

本章我們來了解一下二叉樹這一概念。 目錄 1.樹概念及結構 1.1樹的概念??????? 1.2 樹的特點&#xff1a; 1.3 樹的相關概念 1.4 樹的表示??????? 1.5 樹在實際中的運用&#xff08;表示文件系統的目錄樹結構&#xff09; 2.二叉樹概念及結構 2.1概念 …

Qt 簡約美觀的動畫 擺鐘風格 第十季

&#x1f60a; 今天給大家分享一個擺鐘風格的加載動畫 &#x1f60a; 效果如下: 最近工作忙起來了 , 后續再分享其他有趣的加載動畫吧. 一共三個文件 , 可以直接編譯運行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <Q…

【C++】用文件流的put和get成員函數讀寫文件

題目 編寫一個mycopy程序&#xff0c;實現文件復制的功能。用法是在控制臺輸入&#xff1a; mycooy 源文件名 目標文件名 參數介紹 m a i n main main 函數的參數有兩個&#xff0c;一個int類型參數和一個指針數組。 a r g c argc argc 表示參數的個數。參數為void時 a r g …

機器人 標準DH與改進DH

文章目錄 1 建立機器人坐標系1.1 連桿編號1.2 關節編號1.3 坐標系方向2 標準DH(STD)2.1 確定X軸方向2.2 建模步驟2.3 變換順序2.4 變換矩陣3 改進DH(MDH)3.1 確定X軸方向3.2 建模步驟3.3 變換順序3.4 變換矩陣4 標準DH與改進DH區別5 Matlab示例參考鏈接1 建立機器人坐標系 1.1…

Elasticsearch:如何創建搜索引擎

作者&#xff1a;Jessica Taylor 搜索引擎是生活中我們認為理所當然的事情之一。 每當我們尋找某些東西時&#xff0c;我們都會將一個單詞或短語放入搜索引擎&#xff0c;就像魔術一樣&#xff0c;它會為我們提供一個匹配結果列表。 現在可能感覺不那么神奇了&#xff0c;因為這…

Go-知識struct

Go-知識struct 1. struct 的定義1.1 定義字段1.2 定義方法 2. struct的復用3. 方法受體4. 字段標簽4.1 Tag是Struct的一部分4.2 Tag 的約定4.3 Tag 的獲取 githupio地址&#xff1a;https://a18792721831.github.io/ 1. struct 的定義 Go 語言的struct與Java中的class類似&am…

第二十三章 :Docker 部署 Redis

第二十三章 :Docker Redis 部署 Docker version 25.0.3, build 4debf41 ,Docker Compose version v2.24.2Redis-6.0.6 鏡像 redis:6.0.6-alpineRedis-6.0.6版本 部署規劃 服務器IP192.168.92.105端口6379安裝目錄/home/work/docker-redis-6.0.6數據映射目錄/home/work/do…

最簡單的基于 FFmpeg 的收流器(以接收 RTMP 為例)

最簡單的基于 FFmpeg 的收流器&#xff08;以接收 RTMP 為例&#xff09; 最簡單的基于 FFmpeg 的收流器&#xff08;以接收 RTMP 為例&#xff09;正文結果工程文件下載參考鏈接 最簡單的基于 FFmpeg 的收流器&#xff08;以接收 RTMP 為例&#xff09; 參考雷霄驊博士的文章…

藍凌OA frpt_listreport_definefield.aspx接口存在SQL注入漏洞

免責聲明&#xff1a;文章來源互聯網收集整理&#xff0c;請勿利用文章內的相關技術從事非法測試&#xff0c;由于傳播、利用此文所提供的信息或者工具而造成的任何直接或者間接的后果及損失&#xff0c;均由使用者本人負責&#xff0c;所產生的一切不良后果與文章作者無關。該…

DevStack 部署 OpenStack

Devstack 簡介 DevStack 是一系列可擴展的腳本&#xff0c;用于基于 git master 的最新版本快速調出完整的 OpenStack 環境。devstack 以交互方式用作開發環境和 OpenStack 項目大部分功能測試的基礎。 devstack 透過執行 stack.sh 腳本&#xff0c;搭建 openstack 環境&…

lv20 QT主窗口4

熟悉創建主窗口項目 1 QAction 2 主窗口 菜單欄&#xff1a;fileMenu menuBar()->addMenu(tr("&File")); 工具欄&#xff1a;fileToolBar addToolBar(tr("File")); 浮動窗&#xff1a;QDockWidget *dockWidget new QDockWidget(tr("Dock W…

Threejs之精靈模型Sprite

參考資料 精靈模型Sprite…Sprite模擬下雨、下雪 知識點 注&#xff1a;基于Three.jsv0.155.0 精靈模型Sprite精靈模型標注場景(貼圖)Sprite模擬下雨、下雪 精靈模型Sprite Three.js的精靈模型Sprite和Threejs的網格模型Mesh一樣都是模型對象&#xff0c;父類都是Object3…

【設計者模式】單例模式

文章目錄 1、模式定義2、代碼實現&#xff08;1&#xff09;雙重判空加鎖方式兩次判空的作用&#xff1f;volatile 關鍵字的作用&#xff1f;構造函數私有&#xff1f; &#xff08;2&#xff09;靜態內部類【推薦】&#xff08;3&#xff09;Kotlin中的單例模式lateinit 和 by…