I have to check if a tree is a binary search tree. I'm doing this with an inorder traversal with a temporary array that collects the values. I have to check if the array is ascending order and if it is then I return true:
bool myisBST(Node* node, std::vector<int> v);
bool myisBST(Node* node)
{
return myisBST(node, std::vector<int>());
}
bool myisBST(Node* node, std::vector<int> v)
{
if (node)
{
if (node->left)
return myisBST(node->left, v);
v.push_back(node->data);
if (node->right)
return myisBST(node->right, v);
}
return std::is_sorted(v.begin(), v.end());
}
When binary tree is this:
50
/ \
25 75
/ \ / \
1 12 62 -99
As you can see, the -99 makes this not a binary search tree, but it is still returning true. Is there something wrong with my implementation?
Demo
Two problems:
In myisBST, you are passing v by value, not by reference, so when you pass the vector on recursively, the changes that are made to it don't change its value in the calling method. Simply change the function signature to bool myisBST(Node* node, std::vector<int>& v) to fix this.
The value you should be returning is whether the vector is sorted (as you do in the last line of your method), but instead you are returning prematurely by writing return myisBST(node->left, v); and return myisBST(node->right, v);. You're not actually interested in the return values of these methods; you're just using them to fill the vector inorder. Remove the return from both of these lines.
Following these two fixes, your method works.
First of all, you should probably pass the vector by reference or each recursive call will get a copy and thus the original vector will probably be empty.
Second, you don't even need to create the vector first and then do the check, you can just check the BST property at each node, i.e., the root must be bigger than the left child and smaller than the right child, e.g.,
bool isBST(const Node* root, vector<int>* v) {
if (!root) { return true; }
bool leftBST = true;
if (root->left) {
if (root->data > root->left->data) {
leftBST = isBST(root->left, v);
} else {
// the current node violates the BST precondition
return false;
}
}
// push the root
v->push_back(root->data);
// return false if left subtree is not a BST
if (!leftBST) return false;
if (root->right) {
if (root->data < root->right->data) {
// return whether or not the right subtree is a BST
return isBST(root->left, v);
} else {
// the current node violates the BST precondition
return false;
}
}
// everything good, this is a BST
return true;
}
C++ Program to check if tree is BST or not
struct Node
{
int data;
struct Node* left, *right;
};
bool IsBST(Node* ObjNode)
{
bool leftBST = false;
bool rightBST = false;
if( ObjNode->left != null && ObjNode-left < objNode->data)
{
leftBST = IsBST(ObjNode->left)
}
else if( ObjNode->left == null)
{
leftBST = true;
}
else if( ObjNode->left != null && ObjNode-left >= objNode->data)
{
leftBST = false;
}
if( ObjNode->left != null && ObjNode-left < objNode->data)
{
rightBST = IsBST(ObjNode->right)
}
else if( ObjNode->right == null)
{
rightBST = true;
}
else if( ObjNode->right != null && ObjNode-right >= objNode->data)
{
rightBST = false;
}
return (leftBST && rightBST );
}
In the previous solution, they are keeping a list of the inorder traversal, you really don't need it, you can keep checking with the last traversed element and keep moving forward.
Following solution is the fastest
class Solution {
int lastval = Integer.MIN_VALUE;
int count = 0;
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
boolean left = isValidBST(root.left);
if(!left){
return false;
}
int rootVal = root.val;
if(rootVal == -2147483648 && count == 0 ){
rootVal = rootVal + 1;
}
if( rootVal <= lastval){
return false;
}
count ++;
lastval = root.val;
boolean right = isValidBST(root.right);
if(!right){
return false;
}
return true;
}
}
Related
For binary search tree to see if the tree has duplicated value or not. I took this post order approach.
My goal was to keep the value of the current node and then use other function traverse the tree to see if there is any matching value to that current value, and if it finds any duplicate value it brings "true value". I choose to use recursion as it seems easier to track. but when I ran the program there was no output coming out.
#include "pch.h"
#include <iostream>
using namespace std;
class BSTNode {
public:
int data;
BSTNode* left;
BSTNode* right;
BSTNode() {};
};
BSTNode* newnode(int newdata) { BSTNode *curr = new BSTNode; curr->data = newdata; curr->left = curr->right = nullptr; return curr; }
void print(BSTNode* root) {
if (root != nullptr) {
print(root->left);
cout << root->data << endl;
print(root->right);
}
}
bool checking(BSTNode* parent, int val) {
if (val == parent->data){
bool left = checking(parent->left, val);
bool right = checking(parent->right, val);
return left||right;
}
else
return false;
}
bool assist(BSTNode* parent) {
if (parent != nullptr) {
assist(parent->left);
assist(parent->right);
return checking(parent, parent->data);
}
else return false;
}
int main() {
BSTNode *test = newnode(1);
test->left=newnode(2);
test->right=newnode(3);
test->left->left=newnode(2);
test->right->right=newnode(5);
print(test);
if (assist(test))
cout << "There is duplicated" << endl;
else
cout << "There is no duplicated" << endl;
return 0;
}
Your checking function should look like this:
bool checking(BSTNode* parent, int val) {
if(parent == nullptr) // point 1
return false;
if (val == parent->data){ // point 2
return true;
}
else{
bool left = checking(parent->left, val);
bool right = checking(parent->right, val);
return left||right;
}
}
Your assist function should look something like this:
bool assist(BSTNode* parent) {
if (parent != nullptr) {
if(checking(parent->left, parent->data)) return true; // point 3
if(checking(parent->right, parent->data)) return true;
return assist(parent->left)||assist(parent->right); // point 4
}
else return false;
}
You need to check for null values.
If val is same, why are you still checking? Just stop
You need to check node's value in the left and right subtree.
Recurse it for the child nodes
If you want to check that parent value is different than child values, you might do:
bool checking(const BSTNode* node, int parent_value) {
if (node == nullptr) { return false; }
if (node->data == parent_value) { return true; }
return checking(node->left, node->data)
|| checking(node->right, node->data);
}
bool assist(const BSTNode* parent) {
if (parent == nullptr) {
return false;
}
return checking(parent->left, parent->data)
|| checking(parent->right, parent->data);
}
You could just go through the BST breadth wise with a Deque. Store the values in a set and check if the value is already in the set, if it is return true otherwise wait for the loop to finish and return true. This had the benefit of hash table lookup for values at thr cost of extra storage in O(n) time. Its also easier to follow in my opinion as it's not recursion.
bool hasDuplicate(BSTNode *parent)
{
if (!parent) return false;
std::dueue<BSTNode*> nodes;
std::unordered_set<int> vals;
nodes.push_back(parent);
while(!nodes.empty()) {
BSTNode *node = nodes.pop_front();
int v = nodes->val;
// Check if value exists and return true
if(vals.find(v) != vals.end()) return true;
// Otherwise insert it
vals.insert(v);
// insert left node if exists
if (node->left) nodes.push_back(node->left);
// insert right node if exists
if (node->right) nodes.push_back(node->right);
}
// no dups found
return false;
}
Sorry for bad indents. Did this on phone lol.
My assignment is to find the sum of all nodes on each branch in a binary search tree using recursion, and compare them to a user input value. If the user input value matches a sum of one of the branches, the function should return true.
In other words, the sum of 32+24+21+14=91. The sum of 32+24+28+25=109. The sum of 32+24+28+31=115 etc. I have tried many different methods, but cant seem to figure out how to traverse each branch accurately. So far I have only been able to traverse and find the sum of the left-most branch.
I am using the method of subtracting each node from the user input value. If the value reaches 0 at a Leaf-node, then clearly the user-input matches the node-sum of that branch on the tree.
The particular points of difficulty for me are when the branch diverges, such as at the node [24] and [28]. I clearly am getting something very simple wrong, but I cant figure it out.
Below is the condensed code I've written so far, in the form of two companion methods (also required for the assignment).
public:
bool findBranchSum1(int value) throw (InvalidTreeArgument) {
if (root == nullptr)
throw InvalidTreeArgument();
return(findBranchSum(root, value));
}
private:
bool findBranchSum(NodePtr node, int value) throw (InvalidTreeArgument)
{
bool result = false;
if (root == nullptr)
throw InvalidTreeArgument();
value -= node->getElement(); //subtract current node from user-input value.
cout << "Current Value = " << value << endl; //help track value changes
if (node->getLeftSide() == nullptr && node->getRightSide() == nullptr)
{
if (value == 0)
{
result = true;
return(true);
}
else
return(false);
}
else
{
if (node->getLeftSide() != nullptr)
{
node = node->getLeftSide(); //advance to next Left node
result = findBranchSum(node, value); //recursive call using new node
}
if (node->getRightSide() != nullptr)
{
node = node->getRightSide(); //advance to next Right node
result = findBranchSum(node, value); //recursive call using new node
}
return(result);
}
}
What am I doing wrong, and how can I fix my code to find the sum of each branch on the tree? Thank you in advance. I apologize for any errors in my format, or missing information.
This is wrong:
if (node->getLeftSide() != nullptr)
{
node = node->getLeftSide(); //advance to next Left node
result = findBranchSum(node, value); //recursive call using new node
}
if (node->getRightSide() != nullptr)
{
node = node->getRightSide(); //advance to next Right node
result = findBranchSum(node, value); //recursive call using new node
}
because you move to the left and then to the right branch of the left (node is changed by your assignment), if it exists! Change to:
if (node->getLeftSide() != nullptr)
{
result = findBranchSum(node->getLeftSide(), value);
}
if (node->getRightSide() != nullptr)
{
result = findBranchSum(node->getRightSide(), value);
}
Your return value management is also broken, change it to:
if (node->getLeftSide() != nullptr)
{
result = findBranchSum(node->getLeftSide(), value);
}
if (!result && node->getRightSide() != nullptr) // cut exploration if previous was correct...
{
result = findBranchSum(node->getRightSide(), value);
}
return result;
if you need to stop at the first correct branch.
I might try something like the following.
bool IsLeaf(Node const * node) {
return node && !node->left && !node->right;
}
bool CheckPathSum(Node const * node, int const target, int const sum_so_far) {
if (!node) return false;
int const sum = sum_so_far + node->element;
if IsLeaf(node) && (sum == target) return true;
return CheckPathSum(node->left, target, sum) ||
CheckPathSum(node->right, target, sum);
}
Call as
CheckPathSum(root, target, 0);
In Java, i tried this-
private static void branchSumsUtil(TreeNode root, List<Integer> sumArray, int runningSum) {
if (root == null){
return;
}
int newRunningSum = runningSum + root.key;
if (root.left == null && root.right == null){
sumArray.add(newRunningSum);
}
branchSumsUtil(root.left, sumArray, newRunningSum);
branchSumsUtil(root.right, sumArray, newRunningSum);
}
I am writing a method to check if a given tree is a BST using the inorder traversal method. On executing this method, I get a segfault. Can someone help me correct it?
here, maximum stores the largest value in the BST, and k is initialized to 0. The BST is assumed to have unique positive values. isNull(root) checks if the current node is a null node or not.
bool check(BstNode* root)
{
if (root->data==maximum) return true;
isNull(root);
check(root->left);
if (root->data>k)
{
k=root->data;
}
else
{
return false;
}
check(root->right);
}
Every time when you call check(root->left) and check(root->right), I suppose you need to add sth to determine the left and the right branch is null or not. In your code, you just assume that there is sth in left and right branch and call the check function. I think that's the main reason.
You shouldn't need to specify the maximum value. An elegant solution can be found here
There are two approaches you can do this.
One is top-down approach, first check if current node is valid, if so, then check two subtree. This is very intuitive. you can find the code from #lerman's post:
struct TreeNode {
int data;
TreeNode *left;
TreeNode *right;
};
bool isBST(TreeNode *node, int minData, int maxData) {
if(node == NULL) return true;
if(node->data < minData || node->data > maxData) return false;
return isBST(node->left, minData, node->data) && isBST(node->right, node->data, maxData);
}
if(isBST(root, INT_MIN, INT_MAX)) {
puts("This is a BST.");
} else {
puts("This is NOT a BST!");
}
The other way is a bottom-up approach: first check left substree then right substree and check current tree at last. below is the code for this approach.
bool isValidBST(TreeNode *root) {
int mmin, mmax;
return helper(root, mmin, mmax);
}
bool helper(TreeNode* root, int& mmin, int& mmax) {
if(!root) {
mmin = INT_MAX;
mmax = INT_MIN;
return true;
}
int leftmin, leftmax, rightmin, rightmax;
if(!helper(root->left, leftmin, leftmax))
return false;
if(!helper(root->right, rightmin, rightmax))
return false;
if(root->val > leftmax && root->val < rightmin) {
mmin = min(min(leftmin, rightmin), root->val);
mmax = max(max(leftmax, rightmax), root->val);
return true;
}
else
return false;
}
You might notice that the first approach is pre-order traversal and the second approach is post-order traversal. inorder traversal in inappropriate here because it conflicts with the definition of BST.
and I was trying to implement a binary searching tree:
template <typename T>
bool Tree<T>::search(TreeNode<T> *ptr, const T &key) {
if (ptr == 0) {
cout<<"No such data: "<<key<<" in the tree"<<endl;
return false;
}
else{
if (ptr->data == key) {
cout<<"Find a node whose data is "<<key<<endl;
return true;
}
else if (ptr->data < key) return search(ptr->leftPtr,key);
else return search(ptr->rightPtr,key);
}
}
But the result always returns false no matter the tree contains the key value or not.
Can u guys help me check the code? I tried debug, but still do not know.
Thank you!
Your traversal comparator for left-tree descending is backwards. As such, as soon as you incorrectly descend into the right tree you stand no chance of ever finding that value. Only the root, and root only, will ever be found correctly.
This:
if (ptr->data < key)
return search(ptr->leftPtr,key);
else
return search(ptr->rightPtr,key);
Should read like this:
if (key < ptr->data) // <== note key is LESS THAN node.
return search(ptr->leftPtr,key);
else
return search(ptr->rightPtr,key);
That said, consider this:
template <typename T>
bool Tree<T>::search(TreeNode<T> *ptr, const T &key)
{
if (ptr == 0) {
cout<<"No such data: "<<key<<" in the tree"<<endl;
return false;
}
if (key < ptr->data)
return search(ptr->leftPtr, key);
else if (ptr->data < key)
return search(ptr->rightPtr, key);
cout<<"Found a node whose data is "<< key << endl;
return true;
}
I am trying to implement one bool function that receives List and Int as arguments and should insert int and return true if the int does not exist in the list, or false if it is already there, i have been working for several hours with this function, and the if-else statements can insert sorted int, the problem (and crash) is how to check if the value already exist and return false, here is my function:
declaration of struct
typedef struct E_Type * List;
struct E_Type
{
int data;
List next = 0;
};
and function
bool insert(List & l, int data)
{
List current = l;
do{//check if the int is already in the list
current->data;
current = current->next;
//return false;
}while (current->data == data);
if (l == 0 || l->data > data){
List new_list = new E_Type;
new_list->data = data;
new_list->next = l;
l = new_list;
return true;
}
else if(l->data < data){
insert(l->next, data);
return true;
}
}
do{
//this line doesn't really do anything...
current->data;
//moving current forward, good.
current = current->next;
//If current->data is less than data in the list, it will exit the loop here anyway.
}while (current->data == data);
You also aren't checking whether you have reached the end of the list. Perhaps what you are attempting to do is something like this:
//This is correct for for iterative approach, but I don't think this is really what you need, either...
while(current != null) {
if (current->data == data)
return false;
current = current->next;
}
However, you probably don't want to use iteration like this to make this check in a recursive function, so instead, simply replace that whole bit with:
if (current->data == data)
return false;
And to return the correct value through the recursive calls, you'll want to change:
else if(l->data < data){
insert(l->next, data); //Recursive call
return true; //you don't want to just return true, return what the recursive call returns!
}
To:
else if(l->data < data){
return insert(l->next, data);
}