Open In App

Maximizing Robbery in Binary Tree Houses without Alerting Police

Last Updated : 18 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

There are Houses arranged in the form of a Binary tree. There is only one entrance to the houses which is the root of a tree. It will automatically contact the police if two directly linked houses are broken into on the same night. Given the root of the binary tree, return the maximum amount of money the thief can rob without alerting the police.

Examples:

Input: root = [3, 4, 5, 1, 3, null, 1]
3
/ \
4 5
/ \ \
1 3 1
Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

Input: root = [3, 2, 3, null, 3, null, 1]

3
/ \
2 3
\ \
3 1
Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Approach: To solve the problem follow the below steps:

  • We will start from the root of tree and recursively check whether we can take the current node or not,
  • If we take the current node then we will not be able to take the childs of the node we have to check if the grandchildrens exists or not
  • Then we decide whether to pick them or not, We will do this recursively from the root to leaves of the tree and store the maximum amount that the robber can rob till that node and
  • Modify the value of that node since we can encounter the same node in future we will mark it via using a dp set which ensures that we does not visit that node again and
  • Like this we start updating the node value with the maximum amount that robber can rob at that node level and
  • We update the tree in bottom-up fashion from leaves to the root and when we update the root value it contains the desired result that the maximum amount robber can rob if it starts from the root.

Below is the implementation of above approach:

C++




//code by Flutterfly
#include <iostream>
#include <deque>
#include <unordered_set>
#include <vector> // Add this line for vector support
 
using namespace std;
 
// Definition for a binary tree node.
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
 
class Solution {
public:
    // Function to find the maximum amount of money that can be robbed
    int rob(TreeNode* root) {
        unordered_set<TreeNode*> dp; // A set to store already calculated results for each node
        return robb(root, dp); // Call the recursive function
    }
 
private:
    // Recursive helper function to calculate the maximum amount of money that can be robbed
    int robb(TreeNode* root, unordered_set<TreeNode*>& dp) {
        if (root == nullptr) {
            return 0;
        }
 
        if (dp.find(root) != dp.end()) {
            return root->val; // Return the previously calculated result if available
        }
 
        int notPick = 0;
        int pick = 0;
        int left = 0;
        int right = 0;
 
        if (root->left) {
            left = robb(root->left->left, dp) + robb(root->left->right, dp);
        }
 
        if (root->right) {
            right = robb(root->right->left, dp) + robb(root->right->right, dp);
        }
 
        pick = root->val + left + right;
        notPick = robb(root->left, dp) + robb(root->right, dp);
 
        root->val = max(pick, notPick); // Update the value of the current node
        dp.insert(root); // Add the current node to the set to store the result
 
        return root->val;
    }
};
 
// Function to build a binary tree from a given string representation
TreeNode* buildTree(string s) {
    if (s.empty() || s[0] == 'N') {
        return nullptr;
    }
 
    vector<string> ip;
    size_t pos = 0;
    while ((pos = s.find(' ')) != string::npos) {
        ip.push_back(s.substr(0, pos));
        s.erase(0, pos + 1);
    }
    ip.push_back(s);
 
    TreeNode* root = new TreeNode(stoi(ip[0])); // Create the root of the tree
    size_t size = 0;
    deque<TreeNode*> q;
    q.push_back(root);
    size++;
 
    size_t i = 1;
    while (size > 0 && i < ip.size()) {
        TreeNode* currNode = q.front();
        q.pop_front();
        size--;
 
        string currVal = ip[i];
 
        if (currVal != "N") {
            currNode->left = new TreeNode(stoi(currVal));
            q.push_back(currNode->left);
            size++;
        }
 
        i++;
 
        if (i >= ip.size()) {
            break;
        }
 
        currVal = ip[i];
 
        if (currVal != "N") {
            currNode->right = new TreeNode(stoi(currVal));
            q.push_back(currNode->right);
            size++;
        }
 
        i++;
    }
 
    return root;
}
 
int main() {
    string s = "3 4 5 1 3 N 1";
    TreeNode* root = buildTree(s);
    Solution ob;
    cout << ob.rob(root) << endl; // Print the result
 
    return 0;
}


Java




/*code by Flutterfly */
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
 
// Definition for a binary tree node.
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
 
    TreeNode(int x) {
        val = x;
        left = null;
        right = null;
    }
}
 
class Solution {
    public int rob(TreeNode root) {
        Set<TreeNode> dp = new HashSet<>();
        return robb(root, dp);
    }
 
    private int robb(TreeNode root, Set<TreeNode> dp) {
        if (root == null) {
            return 0;
        }
 
        if (dp.contains(root)) {
            return root.val;
        }
 
        int notPick = 0;
        int pick = 0;
        int left = 0;
        int right = 0;
 
        if (root.left != null) {
            left = robb(root.left.left, dp) + robb(root.left.right, dp);
        }
 
        if (root.right != null) {
            right = robb(root.right.left, dp) + robb(root.right.right, dp);
        }
 
        pick = root.val + left + right;
        notPick = robb(root.left, dp) + robb(root.right, dp);
 
        root.val = Math.max(pick, notPick);
        dp.add(root);
 
        return root.val;
    }
}
 
public class Main {
    public static TreeNode buildTree(String s) {
        // Corner Case
        if (s.length() == 0 || s.charAt(0) == 'N') {
            return null;
        }
 
        // Creating list of strings from input string after splitting by space
        String[] ip = s.split("\\s+");
 
        // Create the root of the tree
        TreeNode root = new TreeNode(Integer.parseInt(ip[0]));
        int size = 0;
        Queue<TreeNode> q = new ArrayDeque<>();
 
        // Push the root to the queue
        q.offer(root);
        size++;
 
        // Starting from the second element
        int i = 1;
        while (size > 0 && i < ip.length) {
            // Get and remove the front of the queue
            TreeNode currNode = q.poll();
            size--;
 
            // Get the current node's value from the string
            String currVal = ip[i];
 
            // If the left child is not null
            if (!currVal.equals("N")) {
                // Create the left child for the current node
                currNode.left = new TreeNode(Integer.parseInt(currVal));
 
                // Push it to the queue
                q.offer(currNode.left);
                size++;
            }
 
            // For the right child
            i = i + 1;
            if (i >= ip.length) {
                break;
            }
            currVal = ip[i];
 
            // If the right child is not null
            if (!currVal.equals("N")) {
                // Create the right child for the current node
                currNode.right = new TreeNode(Integer.parseInt(currVal));
 
                // Push it to the queue
                q.offer(currNode.right);
                size++;
            }
            i = i + 1;
        }
 
        return root;
    }
 
    public static void main(String[] args) {
        String s = "3 4 5 1 3 N 1";
        TreeNode root = buildTree(s);
        Solution ob = new Solution();
        System.out.println(ob.rob(root));
    }
}


Python3




# Definition for a binary tree node.
# class Node:
#     def __init__(self, val):
#         self.val = val
#         self.left = left
#         self.right = right
 
 
from collections import deque
 
 
class Solution:
    def rob(self, root):
        def robb(root):
            if root == None:
                return 0
            if root in dp:
                return root.val
            notPick = pick = 0
            left = right = 0
            if root.left:
                left = robb(root.left.left) + robb(root.left.right)
            if root.right:
                right = robb(root.right.left) + robb(root.right.right)
            pick = root.val + left + right
            notPick = robb(root.left) + robb(root.right)
            root.val = max(pick, notPick)
            dp.add(root)
            return root.val
        dp = set()
        return robb(root)
 
 
class Node:
    def __init__(self, val):
        self.left = None
        self.val = val
        self.right = None
 
 
def buildTree(s):
    # Corner Case
    if(len(s) == 0 or s[0] == "N"):
        return None
 
    # Creating list of strings from input
    # string after spliting by space
    ip = list(map(str, s.split()))
 
    # Create the root of the tree
    root = Node(int(ip[0]))
    size = 0
    q = deque()
 
    # Push the root to the queue
    q.append(root)
    size = size+1
 
    # Starting from the second element
    i = 1
    while(size > 0 and i < len(ip)):
        # Get and remove the front of the queue
        currNode = q[0]
        q.popleft()
        size = size-1
 
        # Get the current node's value
        # from the string
        currVal = ip[i]
 
        # If the left child is not null
        if(currVal != "N"):
 
            # Create the left child for
            # the current node
            currNode.left = Node(int(currVal))
 
            # Push it to the queue
            q.append(currNode.left)
            size = size+1
        # For the right child
        i = i+1
        if(i >= len(ip)):
            break
        currVal = ip[i]
 
        # If the right child is not null
        if(currVal != "N"):
 
            # Create the right child for
            # the current node
            currNode.right = Node(int(currVal))
 
            # Push it to the queue
            q.append(currNode.right)
            size = size+1
        i = i+1
    return root
 
 
s = '3 4 5 1 3 N 1'
root = buildTree(s)
ob = Solution()
print(ob.rob(root))


C#




//code by Flutterfly
using System;
using System.Collections.Generic;
 
// Definition for a binary tree node.
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
 
    public TreeNode(int x) {
        val = x;
        left = null;
        right = null;
    }
}
 
public class Solution {
    public int Rob(TreeNode root) {
        HashSet<TreeNode> dp = new HashSet<TreeNode>();
        return Robb(root, dp);
    }
 
    private int Robb(TreeNode root, HashSet<TreeNode> dp) {
        if (root == null) {
            return 0;
        }
 
        if (dp.Contains(root)) {
            return root.val;
        }
 
        int notPick = 0;
        int pick = 0;
        int left = 0;
        int right = 0;
 
        if (root.left != null) {
            left = Robb(root.left.left, dp) + Robb(root.left.right, dp);
        }
 
        if (root.right != null) {
            right = Robb(root.right.left, dp) + Robb(root.right.right, dp);
        }
 
        pick = root.val + left + right;
        notPick = Robb(root.left, dp) + Robb(root.right, dp);
 
        root.val = Math.Max(pick, notPick);
        dp.Add(root);
 
        return root.val;
    }
}
 
public class Program {
    public static TreeNode BuildTree(string s) {
        // Corner Case
        if (string.IsNullOrEmpty(s) || s[0] == 'N') {
            return null;
        }
 
        // Creating list of strings from input string after splitting by space
        string[] ip = s.Split(' ');
 
        // Create the root of the tree
        TreeNode root = new TreeNode(int.Parse(ip[0]));
        int size = 0;
        Queue<TreeNode> q = new Queue<TreeNode>();
 
        // Push the root to the queue
        q.Enqueue(root);
        size++;
 
        // Starting from the second element
        int i = 1;
        while (size > 0 && i < ip.Length) {
            // Get and remove the front of the queue
            TreeNode currNode = q.Dequeue();
            size--;
 
            // Get the current node's value from the string
            string currVal = ip[i];
 
            // If the left child is not null
            if (currVal != "N") {
                // Create the left child for the current node
                currNode.left = new TreeNode(int.Parse(currVal));
 
                // Push it to the queue
                q.Enqueue(currNode.left);
                size++;
            }
 
            // For the right child
            i = i + 1;
            if (i >= ip.Length) {
                break;
            }
            currVal = ip[i];
 
            // If the right child is not null
            if (currVal != "N") {
                // Create the right child for the current node
                currNode.right = new TreeNode(int.Parse(currVal));
 
                // Push it to the queue
                q.Enqueue(currNode.right);
                size++;
            }
            i = i + 1;
        }
 
        return root;
    }
 
    public static void Main() {
        string s = "3 4 5 1 3 N 1";
        TreeNode root = BuildTree(s);
        Solution ob = new Solution();
        Console.WriteLine(ob.Rob(root));
    }
}


Javascript




// Definition for a binary tree node.
class TreeNode {
    constructor(val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}
 
class Solution {
    rob(root) {
        const dp = new Set();
         
        function robHelper(node) {
            if (!node) return 0;
            if (dp.has(node)) return node.val;
             
            let notPick = 0;
            let pick = 0;
            let left = 0;
            let right = 0;
             
            if (node.left) {
                left = robHelper(node.left.left) + robHelper(node.left.right);
            }
             
            if (node.right) {
                right = robHelper(node.right.left) + robHelper(node.right.right);
            }
             
            pick = node.val + left + right;
            notPick = robHelper(node.left) + robHelper(node.right);
             
            node.val = Math.max(pick, notPick);
            dp.add(node);
            return node.val;
        }
         
        return robHelper(root);
    }
}
 
function buildTree(s) {
    // Corner Case
    if (s.length === 0 || s[0] === 'N') return null;
     
    // Creating list of strings from input
    // string after spliting by space
    const ip = s.split(' ');
     
    // Create the root of the tree
    const root = new TreeNode(parseInt(ip[0]));
    let size = 0;
    const q = [];
     
    // Push the root to the queue
    q.push(root);
    size++;
     
    // Starting from the second element
    let i = 1;
    while (size > 0 && i < ip.length) {
         
        // Get and remove the front of the queue
        const currNode = q[0];
        q.shift();
        size--;
         
        // Get the current node's value
        // from the string
        let currVal = ip[i];
         
        // if the left child is not null
        if (currVal !== 'N') {
             
            // Create the left child for
            // the current node
            currNode.left = new TreeNode(parseInt(currVal));
             
            // Push it to the queue
            q.push(currNode.left);
            size++;
        }
         
        // For the right child
        i++;
        if (i >= ip.length) break;
        currVal = ip[i];
         
        // If the right child is not null
        if (currVal !== 'N') {
             
            // Create the right child for
            // the current node
            currNode.right = new TreeNode(parseInt(currVal));
             
            // Push it to the queue
            q.push(currNode.right);
            size++;
        }
         
        i++;
    }
     
    return root;
}
 
const s = '3 4 5 1 3 N 1';
const root = buildTree(s);
const ob = new Solution();
console.log(ob.rob(root));


Output

9








Time Complexity: O(N) Since we are traversing the whole tree and there are total N nodes in the tree
Auxiliary Space: O(N) to store the answers in dp and the recursion stack space



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads