Determine if an array will generate the same BST provided - Use Recursion - java

I have a problem that I am running into a few issues with, the question is as follows:
Given a pre-constructed Binary Search Tree and an array, determine if the array will produce the same Binary Search Tree.
Now, this question will have a pre-constructed BST for you, and then it will run through the following code:
boolean valid = true;
for (int i = 0;valid && i < arr.length; i ++) {
valid &= tree.checkPattern(arr[i]);
}
//These two methods below are in a different class. For every element in the array,
//the checkPattern method will be called, initially passing in the root of the BST
public void checkPattern(int key) {
recursiveFunction(root, key);
}
public boolean recursiveFunction(TreeNode current, int key){
// Recursive function
}
The goal is to write therecursiveFunction(root, arr[i]), and a hint is that the TreeNode class contains a visited boolean that you are to use to help with this algorithm.
I can't quite seem to figure out how to solve this... Given a key, are you supposed to check to see where it would go in the primary BST, and if the parent has already been visited, then return false?

One way would be to build a new BST from the array, then compare the two trees. Think about how that builds the tree one node at a time.
Now, with a visited flag in every node, we start with all the flags being false, then the logic is:
For each value in the array, look for the node for that value (the target node) in the tree:
If the target node is not found, then answer is no (tree and array have different values).
If the path to the target node steps on any node that has not been visited yet, then answer is no (wrong order).
(optional) If the target node has already been visited, throw IllegalArgumentException (duplicate values in array not allowed).
Mark the target node visited.
Scan the tree (BFS or DFS, doesn't matter), and if you find any unvisited node, then answer is no (tree and array have different values).
If you get here, answer is yes.

Related

Is it possible to change the "find the minimal node" function to also delete the minimal node in a binary search tree?

Just a disclamer, I am doing this for a homework, it's mainly focused on effiency of data structures though.
For a binary search tree i need to implement the delete function, i already created the main traversal system and the only thing i am left doing is to swap the values of a root with the minimal value of it's right subtree, in the case of left and right children. The way i am doing that is through a find the minimal node function.
public int findMin (Tree r1){
int min = r1.key;
while (r1.l != null) {
min = root.l.num;
r1 = r1.l;
}
return min;
}
Great, i found the node i am supposed to delete, my question is, is there a way to also delete the minimal node, without having to traverse the whole tree up until that same node again? Maybe through the function again? Does this function also delete the node or is that not parsed through

Binary Search Tree - adding every node into one result

I try to add every node into one result in iterate way in Java.
For example: if I have a root 5 which has got right node = 7 and left node=3 the result is 15.
I've tried in many ways but I don't know how not to miss any node when my tree is extensive.
I would be grateful for every tip.
Look up tree traversals. There are three basic types: in-order, pre-order, and post-order. Essentially you need to create a function that accepts a node as a parameter and returns an integer.
Assuming you have a node like this:
struct Node {
int value;
Node *right, *left;
}
Something like this would do the trick.
int tree_sum(Node *root) {
if (root == nullptr) return 0; // stops recursion. occurs at leaves
return root->value + tree_sum(root->left) + tree_sum(root->right);
}
Call the function on the root of your tree. This is known as a pre-order traversal. I wrote the code in C++ because I don't know Java.
For tree traversal without recursion use a stack as described here:
https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/

Do not understand the solution for the Binary Tree Maximum Path Sum problem

The website GeeksforGeeks has presented a solution for the problem of Maximum path sum for a binary tree. The question is as follows:
Given a binary tree, find the maximum path sum. The path may start and
end at any node in the tree.
The core of the solution is as follows:
int findMaxUtil(Node node, Res res)
{
if (node == null)
return 0;
// l and r store maximum path sum going through left and
// right child of root respectively
int l = findMaxUtil(node.left, res);
int r = findMaxUtil(node.right, res);
// Max path for parent call of root. This path must
// include at-most one child of root
int max_single = Math.max(Math.max(l, r) + node.data,
node.data);
// Max Top represents the sum when the Node under
// consideration is the root of the maxsum path and no
// ancestors of root are there in max sum path
int max_top = Math.max(max_single, l + r + node.data);
// Store the Maximum Result.
res.val = Math.max(res.val, max_top);
return max_single;
}
int findMaxSum() {
return findMaxSum(root);
}
// Returns maximum path sum in tree with given root
int findMaxSum(Node node) {
// Initialize result
// int res2 = Integer.MIN_VALUE;
Res res = new Res();
res.val = Integer.MIN_VALUE;
// Compute and return result
findMaxUtil(node, res);
return res.val;
}
Res has the following definition:
class Res {
public int val;
}
I am confused about the reasoning behind these lines of code:
int max_single = Math.max(Math.max(l, r) + node.data, node.data);
int max_top = Math.max(max_single, l + r + node.data);
res.val = Math.max(res.val, max_top);
return max_single;
I believe the code above follows this logic but I do not understand WHY this logic is correct or valid:
For each node there can be four ways that the max path goes through
the node:
Node only
Max path through Left Child + Node
Max path through Right Child + Node
Max path through Left Child + Node + Max path through Right Child
In particular, I do not understand why max_single is being returned in the function findMaxUtil when we the variable res.val contains the answer we are interested in. The following reason is given on the website but I do not understand it:
An important thing to note is, root of every subtree need to return
maximum path sum such that at most one child of root is involved.
Could someone provide an explanation for this step of the solution?
In particular, I do not understand why max_single is being returned in the function findMaxUtil when we the variable res.val contains the answer we are interested in.
The problem is that findMaxUtil() really does two things: it returns largest sum of the tree that it's applied to, and it updates a variable that keeps track of the largest sum yet encountered. There's a comment to that effect in the original code, but you edited it out in your question, perhaps for brevity:
// This function returns overall maximum path sum in 'res'
// And returns max path sum going through root.
int findMaxUtil(Node node, Res res)
Because Java passes parameters by value, but every object variable in Java implicitly references the actual object, it's easy to miss the fact that the Res that's passed in the res parameter may be changed by this function. And that's exactly what happens in the lines you asked about:
int max_single = Math.max(Math.max(l, r) + node.data, node.data);
int max_top = Math.max(max_single, l + r + node.data);
res.val = Math.max(res.val, max_top);
return max_single;
That first line finds the maximum of the node itself or the node plus the greatest subtree, and that result is the max path sum going through root. Returning that value on the last line is one thing that this function does. The second and third lines look at that value and consider whether either it or the path that includes both children is larger than any previously seen path, and if so, it updates res, which is the other thing this function does. Keep in mind that res is some object that exists outside the method, so changes to it persist until the recursion stops and findMaxSum(Node), which started the whole thing, returns the res.val.
So, getting back to the question at the top, the reason that the findMaxUtil returns max_single is that it uses that value to recursively determine the max path through each subtree. The value in res is also updated so that findMaxSum(Node) can use it.
You're missing the value of res.val. The algorithm is trying to explore the whole tree, using res.val equal to the maximum path length explored up till then. In each step it iterates recursively across the children and updates res.val with the maximum path length, if higher than the one already present.
Proof:
Assume your algorithm works with trees with height n. For trees with height n+1 there's a root and 2 sub trees of height n. Also consider that findMaxUtil works fine for i<=n and will return the maximum path, starting with the partial root of the sub trees.
So the maximum path in your tree with height n+1 is calculated as follows
findMaxUtil(subtree1)
findMaxUtil(subtree2)
findmaxUtil(subtree1)+root.data
findmaxUtil(subtree2)+root.data
findmaxUtil(subtree1)+findmaxUtil(subtree2)+root.data
res.val
And finally the result is: findmaxUtil(newTree)=max(items 1:6).
Honestly I think the description on that website is very unclear. I'll try to convince you of the reasoning behind the algorithm as best I can.
We have a binary tree, with values at the nodes:
And we are looking for a path in that tree, a chain of connected nodes.
As it's a directed tree, any nonempty path consists of a lowest-depth node (i.e. the node in the path that is closest to the root of the tree), a path of zero or more nodes descending to the left of the lowest-depth node, and a path of zero or more nodes descending to the right of the lowest-depth node. In particular, somewhere in the tree there is a node that is the lowest-depth node in the maximum path. (Indeed, there might be more than one such path tied for equal value, and they might each have their own distinct lowest-depth node. That's fine. As long as there's at least one, that's what matters.)
(I've used "highest" in the diagram but I mean "lowest-depth". To be clear, any time I use "depth" or "descending" I'm talking about position in the tree. Any time I use "maximum" I'm talking about the value of a node or the sum of values of nodes in a path.)
So if we can find its lowest-depth node, we know the maximum value path is composed of the node itself, a sub-path of zero or more nodes descending from (and including) its left child, and a sub-path of zero or more nodes descending from (and including) its right child. It's a small step to conclude that the left and right descending paths must be the maximum value such descending path on each side. (If this isn't obvious, consider that whatever other path you picked, you could increase the total value by instead picking the maximum value descending path on that side.) If either or both of those paths would have a negative value then we just don't include any nodes at all on the negative side(s).
So we have a separate subproblem - given a subtree, what is the value of the maximum value path descending through its root? Well, it might just be the root itself, if all the paths rooted at its children have negative sum, or if it has no children. Otherwise it is the root plus the maximum value descending path of either of those rooted at its children. This subproblem could easily be answered on its own, but to avoid repeated traversals and redoing work we'll combine them both into one traversal of the tree.
Going back to the main problem, we know that some node is the lowest-depth node in the maximum value path. We're not even particularly concerned with knowing when we visit it - we're just going to recursively visit every node and find the maximum value path that has that path as its lowest-depth node, assured that at some point we will visit the one we want. At each node we calculate both the maximum value path starting at that point and descending within the subtree (max_single) and the maximum value path for which this node is the lowest-depth node in the path (max_top). The latter is found by taking the node and "gluing on" zero, one or both of the maximum descending-only paths through its children. (Since max_single is already the maximum value path descending from zero or one of the children, the only extra thing we need to consider is the path that goes through both children.) By calculating max_top at every node and keeping the largest value found in res.val, we guarantee that we will have found the largest of all values by the time we have finished traversing the tree. At every node we return max_single to use in the parent's calculations. And at the end of the algorithm we just pull out the answer from res.val.

Is it possible to add the nodes of Binary Search Tree to a hashset or hashmap

Can we put the nodes of the BST inside either a HashMap or HashSet? If so how do we traverse the BST.This doubt arose while I was solving the TWO SUM BST.
You may put the nodes of a BinarySearchTree into a HashSet, or a HashMap (not sure what the Key,Value pairing would be for the Map). For the HashSet, I would simply traverse the BST in order. To solve the problem that you were given, I would tackle the problem like so:
// Returns true if the BST contains two nodes with elements that
// sum to k, otherwise false
public bool findTarget(TreeNode root, int k){
if(root == null){
throw new NullPointerException();
}
HashSet<Integer> set = new HashSet<Integer>();
return traverse(root, k, set);
}
// Traverses across the BST, in order, adding elements to the set
bool traverse(Node<T> node, int k, HashSet<Node<T>> set){
// If the node has a left child, traverse it first
if(node.left != null){
return traverse(node.left, k, set);
}
// Check to see if the set contains the element that would sum
// with the node we're checking's element to equal k
if(set.contains(k-node.element)){
return true;
}
// Add node's element to the set
set.add(node.element);
// If the node has a right child, traverse it after
if(node.right != null){
return traverse(node.right, k, set);
}
else{
// No two node's with elements summing k exist in the BST,
// since you reached the end and found nothing
return false;
}
}
Yes, you can. A Binary Search Tree has data like any other, and that data can be stored into any other type of collection in Java. Before I tell you how to traverse the BST, let me explain what it is in case you don't know.
A Binary Search Tree is a way of organizing data. The top node is usually called the root, and any data that is less than it will be put to the left of it, and any data that is greater than it will be put to the right of it. These are called the children of it, and the other node is called the parent. For instance, if your root was 2, 1 would be placed to the left of it, and 3 would be placed to the right. However, a node can only have at most 2 children, and the left and right branches can only differ by at most a length of 1. In the case where they differ by more than one, some swapping needs to be done.
To traverse the tree, you must first start at the left branch. With each level you go down, you must first check if the node has a left child. If it does, then go down one level. Keep going down until there are no more left children. This means this is the lowest value. Go up one level, take that as your next value. If it has a right child, take that one next. Continue this until you get to the root. Next, take the root. Finally, traverse the right branch with the same logic. Go to the first right child, and only take if it has no left child. If it does, take the farthest left child. Then take the parent(s). Continue this until you get to the farthest right child, which will be your highest value.

Is this list a Binary Search Tree?

Is the following list a BST or not?
list:{2,5,3,8,6}
Is there a way I can determine this?
Consider that my list will have 100000 elements.
Quick answer is: no. BST is a tree and you have a list.
Long answer is: it may be possible to encode a tree as a list, in which case, whether your list can be decoded into a tree or not will depend on the encoding algorithm. See BST wiki page for more details http://en.wikipedia.org/wiki/Binary_search_tree
In fact your list may be an encoded version of BST. If you read elements from left to right pushing them onto a stack, and whenever you stack has 3 elements do:
parent = pop()
right = pop()
left = pop()
push new Node(parent, left, right)
then you should get a valid BST. But I am only speculating here.
you are having a list , you need to construct BST from this list
A BST has following properties
1- Each node has two children or it is a leaf node
2- For each node its left subtree is smaller than node's value
3- For each node its right subtree is greater than node's value
a bst MUST BE BALANCED i.e. while inserting nodes in a BST , code must respect above 3 conditions.
Searching in a BST is O(log n) operation that is because , each search step divide the search space into two halfs and choose one of the half.
There is a case where search will take O(N) time
Consider following
node = {1,2,3,4,5}
if we make the BST from this node set it will be right alifned that means every next node will be on the right subtree , here if we want to search for a item , we need to traverse whole right sub tree like a link list.

Categories

Resources