337. 打家劫舍 III

中等 深度優先搜索 動態規劃 二叉樹

思路

一個小偷,他一旦偷了一個節點的數值,他就不能偷跟這個節點相鄰的節點。
以右圖舉例,

  • 如果偷了3,就不能偷217
  • 如果偷了17,就不能偷3619。 所以小偷可以選擇偷[19,5,7,3],這是一個合法的方案。

圖片

98. 驗證二叉搜索樹 第二種寫法一樣,全域變數會紀錄最近被遞迴呼叫的函數存下來的結果。

  • 當前節點選擇偷:左樹的根結點不能偷,右樹的根結點不能偷。
  • 當前節點不偷:左樹根節點可偷可不偷;右樹根節點可偷可不偷。

各自選比較好的。

程式碼

全域變數法

class Solution {
public:
    int rob(TreeNode* root) {
        int yes, no; // 偷或不偷能偷到的最大金額
        auto dfs = [&](this auto&&dfs, TreeNode* node) -> void {
            if(!node) { // 空節點, 無法偷到東西, 設定為 0
                yes = 0;
                no = 0;
            }
            else {
                dfs(node->left); // 此時 yes, no 是左樹的 yes, no
                int leftYes = yes, leftNo = no;

                dfs(node->right);
                int rightYes = yes, rightNo = no; // 此時 yes, no 是左樹的 yes, no
                
                yes = node->val + leftNo + rightNo; // 這個節點偷, 那麼子節點都不能偷
                no = max(leftYes, leftNo) + max(rightYes, rightNo);// 這個節點不偷, 那麼子節點各自可偷可不偷
            }
        };
        dfs(root);
        return max(yes, no);
    }
};

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(H)O(H)HH是樹的高度

顯示設定

背景線條
顯示背景網格線條
懸停發光
滑鼠懸停時顯示霓虹效果
聚光燈
跟隨滑鼠的聚光燈效果
背景透明度
開啟透明玻璃效果
主題顏色
自訂主要顏色