Open In App

Finding Bitwise AND sum paths in Binary trees

Last Updated : 24 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a binary tree and a target sum, determine whether there exists a root-to-leaf path in the tree such that the sum of the values of the nodes along the path is equal to the target sum when represented in binary, and the sum of the values of the nodes along the path is calculated by performing a bitwise AND operation between the binary representation of the values of each node in the path.

Examples:

Consider a binary tree with the following structure:

           7
       /      \
     5        8
    / \       / \
15 13 12 16

Input: Target_sum = 6
Output: False
Explanation: The binary representation of 6 is 110. If we perform the bitwise AND operation between the binary representation of the values of each node along the path from root to leaf, we never get 110 from any root-to-leaf path.

Input: Target_sum = 5
Output: True
Explanation: The binary representation of 5 is 101. If we perform the bitwise AND operation between the binary representation of the values of {7, 5, 15} then we get 5.

Approach: This problem can be solved using a recursive depth-first search approach.

  • Start from the root of the tree and perform a bitwise AND operation between the binary representation of the current node’s value and the previous result. 
  • Check if the current node is a leaf node and whether the current result is equal to the target sum in binary representation, if both conditions are satisfied, we return True. 
  • Otherwise, recursively traverse the left and right subtrees of the current node, passing the updated result to the next call. 
  • If no root-to-leaf path exists such that the sum of the values of the nodes along the path is equal to the target sum, the algorithm will return False.

Follow the steps to solve the problem:

  • Create a function called hasPathSum that takes in a binary tree root and a target sum targetSum, and returns a boolean value indicating whether there exists a root-to-leaf path in the tree with the given condition.
  • Create an inner function called dfs to traverse the binary tree recursively that takes in a node and the previous result, and returns a boolean value indicating whether there exists a root-to-leaf path in the subtree rooted at the given node with the given condition.
  • Inside the dfs function, if the given node is NULL, return False.
  • Calculate the current result by performing a bitwise AND operation between the previous result and the value of the current node.
    • curr_result = prev_result & node->val.
  • If the given node is a leaf node and the current result is equal to the target sum, return True.
    • if (!node->left && !node->right), return curr_result == targetSum
  • Recursively call the dfs function on the left and right subtrees with the updated current result.
  • Return the OR of the results returned by the left and right subtree calls.
  • Call the dfs function with the root node and an initial result of 0.
  • Return the result returned by the dfs function.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Definition for a binary tree node
class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    // constructor
    TreeNode(int val = 0, TreeNode* left = nullptr,
             TreeNode* right = nullptr)
        : val(val), left(left), right(right)
    {
    }
};
 
class GFG {
public:
    bool hasPathSum(TreeNode* root, int targetSum)
    {
 
        // Define inner function dfs to
        // traverse the binary tree
        // recursively
        function<bool(TreeNode*, int)> dfs
            = [&](TreeNode* node, int prev_result) -> bool {
            // If node is NULL, return
            // false (base case)
            if (!node)
                return false;
 
            // Calculate the current
            // result by performing
            // bitwise AND operation
            // between previous result
            // and node value
            int curr_result = prev_result & node->val;
 
            // If node is a leaf node and
            // current result is equal to
            // targetSum, return true
            if (!node->left && !node->right)
                return curr_result == targetSum;
 
            // Recursively call dfs function
            // on left and right subtrees
            // with updated current result
            return dfs(node->left, curr_result)
                   || dfs(node->right, curr_result);
        };
 
        // Call the dfs function with root
        // node and initial result
        // of root value
        return dfs(root, root->val);
    }
};
 
// Drivers code
int main()
{
 
    // create a binary tree
    /*
           7
         /  \
        5    8
      /  \  / \
     15 13 12 16
    */
    TreeNode* root = new TreeNode(7);
    root->left = new TreeNode(5);
    root->right = new TreeNode(8);
    root->left->left = new TreeNode(15);
    root->left->right = new TreeNode(13);
    root->right->left = new TreeNode(12);
    root->right->right = new TreeNode(16);
 
    // Create a solution object
    GFG obj;
    int target_sum = 6;
 
    // In this case, the target sum is 6
    // which is represented in
    // binary as 110
    if (obj.hasPathSum(root, target_sum))
        cout << "True" << endl;
 
    // Else return False
    else
        cout << "False" << endl;
 
    target_sum = 5;
 
    // In this case, the target sum is 5
    // which is represented in
    // binary as 101
    if (obj.hasPathSum(root, target_sum))
        cout << "True" << endl;
    else
        cout << "False" << endl;
 
    return 0;
}


Java




// Java program for the above approach
 
// Definition for a binary tree node.
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    // constructor
    TreeNode(int val)
    {
        this.val = val;
        left = null;
        right = null;
    }
 
    TreeNode(int val, TreeNode left, TreeNode right)
    {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
 
class Solution {
    boolean dfs(TreeNode node, int prev_result,
                int targetSum)
    {
        // if node is null, return false (base case)
        if (node == null)
            return false;
        // calculate the current result by performing
        // bitwise AND operation between previous result
        // and node value
        int curr_result = prev_result & node.val;
 
        // if node is a leaf node and current result is
        // equal to targetSum, return true
        if (node.left == null && node.right == null)
            return curr_result == targetSum;
 
        // recursively call dfs function on left and
        // right subtrees with updated current result
        return dfs(node.left, curr_result, targetSum)
            || dfs(node.right, curr_result, targetSum);
    }
    public boolean hasPathSum(TreeNode root, int targetSum)
    {
        // define inner function dfs to traverse the binary
        // tree recursively
 
        // call the dfs function with root node and initial
        // result of root value
        return dfs(root, root.val, targetSum);
    }
}
 
// Example usage
public class GFG {
    public static void main(String[] args)
    {
        // create a binary tree
        /*
             7
           /  \
          5    8
        /  \  / \
       15 13 12 16
      */
        TreeNode root = new TreeNode(7);
        root.left = new TreeNode(5);
        root.right = new TreeNode(8);
        root.left.left = new TreeNode(15);
        root.left.right = new TreeNode(13);
        root.right.left = new TreeNode(12);
        root.right.right = new TreeNode(16);
        // create a solution object
        Solution sol = new Solution();
 
        // In this case, the target sum is 6
        // which is represented in binary as 110
        if (sol.hasPathSum(root, 6))
            System.out.println("True");
        else
            System.out.println("False"); // False
 
        // In this case, the target sum is 5
        // which is represented in binary as 101
        if (sol.hasPathSum(root, 5))
            System.out.println("True"); // True
        else
            System.out.println("False");
    }
}
 
// This code is contributed by Susobhan Akhuli


Python3




# Python program for the above approach
# 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 hasPathSum(self, root: TreeNode, targetSum: int) -> bool:
        # define inner function dfs to traverse the binary
        # tree recursively
        def dfs(node, prev_result):
            # if node is None, return False (base case)
            if not node:
                return False
             
            # calculate the current result by performing
            # bitwise AND operation between previous result
            # and node value
            curr_result = prev_result & node.val
             
            # if node is a leaf node and current result is
            # equal to targetSum, return True
            if not node.left and not node.right:
                return curr_result == targetSum
             
            # recursively call dfs function on left and
            # right subtrees with updated current result
            return dfs(node.left, curr_result) or dfs(node.right, curr_result)
         
        # call the dfs function with root node and initial
        # result of root value
        return dfs(root, root.val)
 
 
# Example usage
# create a binary tree
# 7
#       /   \
# 5     8
#     / \   / \
# 15 13 12 16
root = TreeNode(7)
root.left = TreeNode(5)
root.right = TreeNode(8)
root.left.left = TreeNode(15)
root.left.right = TreeNode(13)
root.right.left = TreeNode(12)
root.right.right = TreeNode(16)
 
# create a solution object
sol = Solution()
 
# In this case, the target sum is 6
# which is represented in binary as 110
print(sol.hasPathSum(root, 6))  # False
 
# In this case, the target sum is 5
# which is represented in binary as 101
print(sol.hasPathSum(root, 5))  # True
 
# This code is contributed by Susobhan Akhuli


C#




// C# program for the above approach
using System;
 
// Definition for a binary tree node.
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    // constructor
    public TreeNode(int val)
    {
        this.val = val;
        left = null;
        right = null;
    }
 
    public TreeNode(int val, TreeNode left, TreeNode right)
    {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
 
public class Solution {
    public bool dfs(TreeNode node, int prev_result,
                    int targetSum)
    {
        // if node is null, return false (base case)
        if (node == null) {
            return false;
        }
        // calculate the current result by performing
        // bitwise AND operation between previous result
        // and node value
        int curr_result = prev_result & node.val;
 
        // if node is a leaf node and current result is
        // equal to targetSum, return true
        if (node.left == null && node.right == null) {
            return curr_result == targetSum;
        }
 
        // recursively call dfs function on left and
        // right subtrees with updated current result
        return dfs(node.left, curr_result, targetSum)
            || dfs(node.right, curr_result, targetSum);
    }
 
    public bool HasPathSum(TreeNode root, int targetSum)
    {
        // define inner function dfs to traverse the binary
        // tree recursively
 
        // call the dfs function with root node and initial
        // result of root value
        return dfs(root, root.val, targetSum);
    }
}
 
// Example usage
public class GFG {
    public static void Main(string[] args)
    {
        // create a binary tree
        /*
            7
           / \
          5   8
         / \ / \
        15 13 12 16
        */
        TreeNode root = new TreeNode(7);
        root.left = new TreeNode(5);
        root.right = new TreeNode(8);
        root.left.left = new TreeNode(15);
        root.left.right = new TreeNode(13);
        root.right.left = new TreeNode(12);
        root.right.right = new TreeNode(16);
 
        // create a solution object
        Solution sol = new Solution();
 
        // In this case, the target sum is 6
        // which is represented in binary as 110
        if (sol.HasPathSum(root, 6)) {
            Console.WriteLine("True");
        }
        else {
            Console.WriteLine("False"); // False
        }
 
        // In this case, the target sum is 5
        // which is represented in binary as 101
        if (sol.HasPathSum(root, 5)) {
            Console.WriteLine("True"); // True
        }
        else {
            Console.WriteLine("False");
        }
    }
}
 
// This code is contributed by Susobhan Akhuli


Javascript




// JavaScript program for the above approach
// Definition for a binary tree node.
class TreeNode {
    constructor(val = 0, left = null, right = null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
 
class Solution {
    hasPathSum(root, targetSum) {
        // define inner function dfs to traverse the binary
        // tree recursively
        function dfs(node, prev_result) {
            // if node is None, return False (base case)
            if (!node) {
                return false;
            }
             
            // calculate the current result by performing
            // bitwise AND operation between previous result
            // and node value
            let curr_result = prev_result & node.val;
             
            // if node is a leaf node and current result is
            // equal to targetSum, return True
            if (!node.left && !node.right) {
                return curr_result == targetSum;
            }
             
            // recursively call dfs function on left and
            // right subtrees with updated current result
            return dfs(node.left, curr_result) || dfs(node.right, curr_result);
        }
         
        // call the dfs function with root node and initial
        // result of root value
        return dfs(root, root.val);
    }
}
 
// Example usage
// create a binary tree
//          7
//       /   \
//      5     8
//     / \   / \
//    15 13 12 16
let root = new TreeNode(7);
root.left = new TreeNode(5);
root.right = new TreeNode(8);
root.left.left = new TreeNode(15);
root.left.right = new TreeNode(13);
root.right.left = new TreeNode(12);
root.right.right = new TreeNode(16);
 
// create a solution object
let sol = new Solution();
 
// In this case, the target sum is 6
// which is represented in binary as 110
console.log(sol.hasPathSum(root, 6));  // False
 
// In this case, the target sum is 5
// which is represented in binary as 101
console.log(sol.hasPathSum(root, 5));  // True
 
// This code is contributed by Tapesh(tapeshdua420)


Output

False
True

Time Complexity: O(N), where N is the number of nodes in the binary tree. This is because we visit each node in the tree exactly once during the depth-first search.
Auxiliary Space: O(h), where h is the height of the binary tree. This is because the space used by the call stack during the depth-first search is proportional to the height of the tree. In the worst case, where the tree is skewed, the height of the tree can be equal to the number of nodes in the tree, giving a space complexity of O(N). However, in the best case, where the tree is perfectly balanced, the height of the tree is log(N), giving a space complexity of O(log(N)).



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads