I'm trying to find the min for a binary tree, NOT binary search tree, but can't get the answer, code is below. Please tell me what is wrong.
Edit: So with the help of a poster, I was able to get the code working. I made code 1 to work, but I don' understand why in code 2, we need to check for Math.min again when in code 1 we didn't have to do that.
Code 1:
static int min = 0;
static public int findMinimumValue(Node root) {
min = root.data;
findMinimumValue(root, root.data);
return min;
}
static public int findMinimumValue(Node root, int x) {
if(root == null) {
return min;
} else {
if(root.data < min) {
min = root.data;
}
int left = findMinimumValue(root.left, x);
int right = findMinimumValue(root.right, x);
return min;
}
}
Code 2:
static public int findSecondMinimumValue(Node root) {
// min = root.data;
return findSecondMinimumValue(root, root.data);
}
static public int findSecondMinimumValue(Node root, int min) {
if(root == null) {
return min;
} else {
if(root.data < min) {
min = root.data;
}
int left = findSecondMinimumValue(root.left, min);
int right = findSecondMinimumValue(root.right, min);
return Math.min(left, right);
}
}
Step 1: Identify the problem
Follow through what all you have done in the code base. Let's make a binary tree:
5
/ \
2 1
Clearly the minimum is 1, right? So, follow through your code with this example.
public int findMinimumValue(TreeNode root) {
return findMinimumValue(root, root.val);
}
The root will be the starting point.
int left = findMinimumValue(root.left, min);
int right = findMinimumValue(root.right, min);
This is what each and every node will see (if it is not null). It's a recursive call to the left, then to the right after it has gone as left as it can.
finalMinimumValue(TreeNode(5), 5)
Calls the following:
int left = finalMinimumValue(TreeNode(2), 5);
int right = finalMinimumValue(TreeNode(1), 5)
finalMinimumValue(TreeNode(2), 5)
Calls the following:
int left = finalMinimumValue(null, 5);
int right = finalMinimumValue(null, 5)
finalMinimumValue(null, 5)
Does the following code:
return min;
What is min? min is, well, 5.
Does that make sense? We traversed over 2, yet still kept the min as 5.
Step 2: Fix the problem
We concluded in step 1 that it makes no sense for us to not update min if we are currently at a node that is not the minimum. So, let's update it before we recursively go down also.
public int findMinimumValue(TreeNode root) {
return findMinimumValue(root, root.val);
}
public int findMinimumValue(TreeNode root, int min) {
if (root == null) {
return min;
} else {
// update your min variable here by comparing it with the node you currently are at!
int left = findMinimumValue(root.left, min);
int right = findMinimumValue(root.right, min);
if (left < min) {
min = left;
}
if (right < min) {
min = right;
}
return min;
}
}
Step 3: Test the solution
Let's follow through with the same example. We are expecting it to say it is 1.
5
/ \
2 1
1: Compute left for the root node
Our Node's value is 5. Is 5 less than our Node's value (5)? No. So, don't update the min.
Next, call the left child, Node(2)
2: Compute the min to return for Node 2
Our Node's value is 2. Is 5 less than our Node's value (2)? Yes! So, update our min value.
Now min is 2.
Next, call the left child, null. Since its left child is null, we return min, which is 2.
Now, call the right child, null. Since its right child is null, we return min, which is 2.
Well, left equals 2, right equals 2. So, return 2!
3: Compute the min to return for Node 1
Our Node's value is 1. Is 5 less than our Node's value (1)? Yes! So update the min.
Now min is 1.
Next, call the left child, null. Since its left child is null, we return min, which is 1.
Now, call the right child, null. Since its right child is null, we return min, which is 1.
Well, left equals 1, right equals 1. So, return 1!
4: Compute the min to return for the root node.
The left returned us 2.
The right returned us 1.
Since 1 is less than 2, 1 is the answer.
It works!
Related
I'm trying to find the minimum height of a tree. I modified my original algorithm for finding the max height of a tree (but this time, just using Math.min instead of Math.max).
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if(root == null){return Integer.MAX_VALUE;}
if(root.left == null && root.right == null){return 1;}
int left = minDepth(root.left);
int right = minDepth(root.right);
return Math.min(left, right) + 1;
}
}
It was able to pass a normal tree, and the Integer.MAX_VALUE is there for the test case of
2
\
3
\
4
\
5
However, the code will NOT pass the test case of simply having an empty input "[]".
Is there any changes I can make to this code that will pass? I'm scratching my head and wondering if I should delete it and start from scratch. I feel very close, though.
LC Question: https://leetcode.com/problems/minimum-depth-of-binary-tree/
The problem in your code, is when the tree is skewed for example, it will return the minimum depth-value for subtree's it traversed so far.
if you consider the following tree:
2
\
3
\
4
\
5
it should return -2147483648.
carefully check the left and right subtree of root, which is 2,
left subtree depth value: Integer.MAX_VALUE (+1) = -2147483648
right subtree depth value: 4 (+1) = 5
now check next element which is 3,
minimum value found so far: -2147483648
right subtree depth value: 3 (+1) = 4
now check next element which is 4,
minimum value found so far: -2147483648
right subtree depth value: 2 (+1) = 3
and so on.. and at the end will come up with the minimum number we have found so far, which is -2147483648 or in case of 2147483647 when the tree is empty or null.
you need to change the logic in which case it should take minimum depth-value for maximum depth-ed node:
I wrote one solution for you, check if it works:
int min = Integer.MAX_VALUE;
public int minDepth(TreeNode root) {
if(root == null){
return 0; /* return 0 when the tree is empty */
}
/* visit each node in DFS manner, and found maximum depth-ed node possible */
minDepth(root, 0);
return min+1;
}
private void minDepth(TreeNode root, int count){
if(root == null){
return;
}else if(root.left == null && root.right == null){
/* replace the minimum value with maximum-depth node counter */
if(min > count){
min = count;
}
}else{
count += 1;
minDepth(root.left, count);
minDepth(root.right, count);
}
I want to find a target value 4 firstly appeared place in a sequence [1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6]. when I use java.util.Arrays.binaySearch, it returns index is 9, but I expected 7.
I look java.util.Arrays.binaySearch source code
and I found some comments:
If the array contains multiple elements with the specified value, there is no guarantee which one will be found.
So how to implement a lower_bound binary search algorithm in Java, which returns the target value firstly appeared place.
Note: The lower_bound concept comes from C++, but I don't understand C++ well.
I think the implementation below will do the job correctly:
int firstOccurrence(int[] sequence, int x) {
int min = 0;
int max = sequence.length - 1;
int result = -1;
while (min <= max)
{
// find the mid value and compare it with x
int mid = min + ((max - min) / 2);
// if x is found, update result and search towards left
if (x == sequence[mid]) {
result = mid;
max = mid - 1;
} else if (x < sequence[mid]) {
// discard right half
max = mid - 1;
} else {
// discard left half
min = mid + 1;
}
}
// return the leftmost index equal to x or -1 if not found
return result;
}
Edit:
Change the way to compute mid to avoid overflow with larger sums
// Previously, can overflow since we add two integer
int mid = (min + max) / 2;
// Now
int mid = min + ((max - min) / 2);
// Another way using the unsigned right shift operator
int mid = (low + high) >>> 1;
// The left operands value (low + high) is moved right
// by the number of bits specified (2 in this case) by the right operand and
// shifted values are filled up with zeros.
// The >>> treats the value as unsigned
Building on this answer to another binary search question:
How can I simplify this working Binary Search code in C?
This is a search that is equivalent to lower_bound from C++. It returns the number of elements smaller than the value you want to find. That would be
the index of the first occurrence, or where one would be inserted if there is no occurrence:
int numSmaller(int[] seq, int valueToFind)
{
int pos=0;
int limit=seq.length;
while(pos<limit)
{
int testpos = pos+((limit-pos)>>1);
if (seq[testpos]<valueToFind)
pos=testpos+1;
else
limit=testpos;
}
return pos;
}
Note that we only need to do one comparison per iteration.
The linked answer highlights several advantages of writing a binary search this way.
It think it will help you
public static boolean binarysearch(int[] data, int target, int low, int high){
if(low>high){
System.out.println("Target not found");
return false;}
else{
int mid=(low+high)/2;
if(target==data[mid])
return true;
else if(target<data[mid])
return binarysearch(data, target, low, high);
else
return binarysearch(data, target, low, high);
}
}
I am trying to solve a question of the balanced binary tree.
Given a binary tree : [1,2,2,3,3,null,null,4,4]. Determine if it's a balanced tree or not.
And I had the solution:
public boolean isBalanced(TreeNode root) {
int height = heightCalculation(root);
if(height > 1) return false;
else
return true;
}
public int heightCalculation(TreeNode root){
if(root == null)
return 0;
int left_height = Integer.MIN_VALUE;
int right_height = Integer.MIN_VALUE;
left_height = heightCalculation(root.left);
right_height =heightCalculation(root.right);
return Math.abs(left_height - right_height);
}
The tree structure looks like:
1
/ \
2 2
/ \
3 3
/ \
4 4
It's returning true but the actual answer is false.
Can someone help me in fixing the issue ? I have kept the tree structure for your reference
The problem is that the heightCalculation function which is supposed to calculate the heights of right and left sub-trees and find the difference always returns 0. Following is the correct implementation for calculating the height of a binary tree:
int height(TreeNode node) {
if(node == null) {
return 0;
} else {
return 1 + Math.max(height(node.left), height(node.right));
}
}
Use the above function to find the heights of the sub trees and then calculate the difference.
Basically what I wanted to is if a number n is divisible by b for a(count) times, then find the a(count), and divide n by b for a(count) times.
That is,
count = 0;
while(n%b == 0)
n=n/b;
count = count + 1;
How to optimize this, so that everything can be obtained in one step
You can do it in O(log(a)) by applying binary search, on a sorted "list" to find the last element that equals 1.
The list is metaphoric, and each element in it is calculated on the fly when queried by a simple calculation:
list[i] = 1 n % a^i == 0
0 otherwise
You can first find the range of possible a's using exponention:
curr = b
tempA = 1
while n % curr == 0:
curr = curr * curr
tempA = tempA *2
And then, run the binary search on the range [tempA/2, tempA]. This range is of size (a/2), so finding the last "element" that the symbolic list holds 1 - is done in O(loga) multiplications.
Code + Demo:
private static int specialBinarySearch(int n, int b, int aLow, int aHigh) {
if (aHigh == aLow) return aHigh;
int mid = (aHigh - aLow)/2 + aLow;
//pow method can be optimized to remember pre-calculated values and use them
int curr = (int)Math.round(Math.pow(b, mid));
if (n % curr == 0) { //2nd half, or found it:
if (n % (curr*b) != 0) return mid; //found it
return specialBinarySearch(n, b, mid+1, aHigh); //2nd half
}
else return specialBinarySearch(n, b, aLow, mid); //first half
}
public static int findA(int n, int b) {
int curr = b;
int tempA = 1;
while (n % curr == 0) {
curr = curr * curr;
tempA = tempA *2;
}
return specialBinarySearch(n, b, tempA/2, tempA);
}
public static void main(String args[]) {
System.out.println(findA(62,2)); //1
System.out.println(findA(1024,2)); //10
System.out.println(findA(1,2)); //0
System.out.println(findA(100,2)); //2
System.out.println(findA(6804,3)); //5
}
You cannot solve this in O(1) but there is a different kind of approach to this problem if you start using a numeric system where b is the base.
For example, if we have a number like 154200, and b is 10, we know the answer is 2 here immediately because we can simply count how many zeros there are on the right hand side.
Similarly, in binary, if b is 2, you simply count how many zeros there are on the right side with a binary representation.
If b is 5, we have to use the odd base 5 representation where a number like 8 is represented as 13. Again we know that the answer for a is zero is n=8 and b=5 because there are no zeros on the right hand side.
This won't necessarily give you speed gains except possibly in cases where b is a power of two where you can use bitwise logic to deduce the answer, but it gives you a different kind of way of looking at the problem lexically by digits instead of through arithmetic.
How to find sum of node's height in a binary tree recursively?
Example:
public int totalHeight() {
return totalHeight(root);
}
private int totalHeight(BinaryNode<AnyType> n) {
int totalHeight = 0;
if (n.left == null && n.right == null)
return totalHeight;
if (n.left != null && n.right != null)
return totalHeight + 1
+ Math.max(totalHeight(n.left), totalHeight(n.right));
if (n.left != null)
return totalHeight + 1 + Math.max(totalHeight(n.left), -1);
if (n.right != null)
return totalHeight + 1 + Math.max(-1, totalHeight(n.right));
return totalHeight;
}
I have tried this, but it only get the height of the tree instead of sum of all node's height.
I feel difficult to track the counter in recursion, it seems that the totalHeight set to 0 every recursive call. This is not good.
A simple version would be to do a two-pass process where you first record for each node the height it is at, and then iterate through the nodes to sum them up. This method can be made recursive, but it is easy to do it in just one pass by summing as you calculate the height.
public static int totalHeightSum = 0;
private int calculateHeightAndAdd ( Node n )
{
if ( n == null )
return 0;
int leftHeight = calculateHeightAndAdd ( n.left );
int rightHeight= calculateHeightAndAdd ( n.right);
int myHeight = 1 + Math.max ( leftHeight, rightHeight );
totalHeightSum += myHeight;
return myHeight;
}
Recurcively find height of each node and keep adding to a static variable. Alternately, you could memorize the height and store in each node and then do another recursion to add them up.
The recursion should return the height of the node n and not the total heights of each of the nodes in the subtree.
Given your implementation of the height of a node, let's simply call it height(BinaryNode<?>), you can:
if you have access to all the nodes in a collection:
int sumHeight(List<BinaryNode<?>> nodes) {
int sum = 0;
for (BinaryNode<?> node: nodes) {
sum += height(node);
}
return sum;
}
if you only have access to the nodes in a tree structure:
int sumHeight(BinaryNode<?> node) {
if (node == null) return 0;
return height(node) + sumHeight(node.left) + sumHeight(node.right);
}
It would be interesting to see if there're algo's that can do the calculation in one recursion (maybe some backtracking algo?).
Ok. I have come out a solution.
a) if n == null return 0
b) if n.left == null && n.right == null return 0
c) the total height is total height of left + total height of right + the height of it self
the height of itself is:
1) if left side is larger, then total height of left minus total height of left's left
2) if right side is larger, then total height of right minus total height of right's right
public int totalHeight() {
return totalHeight(root);
}
private int totalHeight(BinaryNode<AnyType> n) {
if (n == null)
return 0;
else if (n.left == null && n.right == null)
return 0;
else
return totalHeight(n.left)
+ totalHeight(n.right)
+ (totalHeight(n.left) > totalHeight(n.right) ? totalHeight(n.left)
- (n.left == null ? 0 : totalHeight(n.left.left))
: totalHeight(n.right)
- (n.right == null ? 0
: totalHeight(n.right.right))) + 1;
}
I am assuming you are not updating heights during insertion.
Solution:
I would traverse through the tree in a inorder way. So I first declare root.height=0.
And then say
BinaryNode right;
BinaryNode left;
BinaryNode parent;
static int level;
int height;
if(left!=null)
{
left.height=left.parent.height+1;
level=level+left.height;
left.yourMethod();
}
if(right!=null)
{
right.height= right.parent.height+1;
level=level+right.height;
right.yourMethod();
}
So you will now have level that stores all the heights.
Alternative method can be Breadth first search traversal using a queue, but the answer would be the same.
Hope this helps.
void addHeights(class tree* root, int depth, int& sum)
{
if(root)
{
addHeights(root->left, depth+1, sum);
addHeights(root->right, depth+1, sum);
sum += depth;
}
}
public int sum(){
return sum(root);
}
private int sum(BinaryNode <?> n){
if(n == null)
return 0;
else
return n.data + sum(n.left) + sum(n.right);
}
I need more data to assess your code though I am assuming that you called the data inside the node "data".
So if the node is null it means you have reached the end of the tree and returns 0. Otherwise it takes the data and traverses towards the left then to the right. With each recursion they are being added until they are no more nodes left to be added.
private int maxHeight(BinaryNode<AnyType> n) {
if (n ! = null) return 0;
int leftheight = maxHeight(n.left);
int rightheight = maxHeight(n.right);
return (leftheight > rightheight) ? leftheight + 1 : rightheight + 1;
}
So far you have known the 4 cases to count the height
The essence is to continue to go left or right node if the left child or the right child exist.
if exist, return 1.
The counting function goes in the last statement. That is to get the largest height counted.
The main course is to get familiar with recursion and the programming stack when the method is working.