1. 程式人生 > 其它 >刷題-力扣-337. 打家劫舍 III

刷題-力扣-337. 打家劫舍 III

337. 打家劫舍 III

題目連結

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/house-robber-iii
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

題目描述

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

計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。

示例 1:

輸入: [3,2,3,null,3,null,1]

     3
    / \
   2   3
    \   \ 
     3   1

輸出: 7 
解釋:小偷一晚能夠盜取的最高金額 = 3 + 3 + 1 = 7.

示例 2:

輸入: [3,4,5,1,3,null,1]

    3
    / \
   4   5
  / \   \ 
 1   3   1

輸出: 9
解釋:小偷一晚能夠盜取的最高金額= 4 + 5 = 9.

題目分析

  1. 根據題目描述,計算不相連節點的最大權值和
  2. 假設f(x)表示選擇節點x的情況下最大權值和,g(x)表示不選擇節點x的情況下最大權值和
  3. 節點x的最大權值和有如下狀態轉移方程
    f(x)=x->val+g(x->left)+g(x->right)
    g(x)=max(g(x->left),f(x->left))+max(g(x->right),f(x->right))

程式碼

/**
 * 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 {
private:
    unordered_map<TreeNode*, int> f, g;

public:
    int rob(TreeNode* root) {
        dfs(root);
        return max(f[root], g[root]);
    }

private:
    void dfs(TreeNode* root) {
        if (!root) return;
        dfs(root->left);
        dfs(root->right);
        f[root] = root->val + g[root->left] + g[root->right];
        g[root] = max(f[root->left], g[root->left]) + max(f[root->right], g[root->right]);
    }
};