How to write the depth() method without the Node inside the parameter? - java

There is an assignment where we have to modify the Binary Tree with the following methods. I was able to write all the methods to work, including the depth() method. However, as I read the question carefully I noticed that I wrote this method with a node inside the parameters instead of a variable (in this case its int key).
Here is my code:
public int getDepth(Node node) {
if (node == null) {
return 0;
} else {
int leftSubtreeDepth = getDepth(node.leftChild);
int rightSubtreeDepth = getDepth(node.rightChild);
if (leftSubtreeDepth > rightSubtreeDepth) {
return (leftSubtreeDepth + 1);
} else {
return (rightSubtreeDepth + 1);
}
}
}
The output is correct when I used this code. However, now that I know that I have to write the depth method with an int key variable (aka. public int getDepth(int key) ), is there anything I can do to change this code up? I hope it's just a small change/fix since it took me a while to write this code.

Related

Recursive function that returns a count of elements with the specified value in a linked list

I am working on a function, countH(), that is supposed to count the amount of times a given number appears in a linked list. For some reason, I cannot get this to work recursively. I have tried a number of different solutions but I guess I can't get something in the correct place. Sorry if I am asking the question poorly, I struggle to understand recursion formatting sometimes.
Here is the function:
public int count(int i) {
return countH(first, i);
}
private int countH(Node front, int i) { // TODO
int cter = 0;
if (front.next==null) {
return 0;
}
if(front.item == i)
cter++;
return countH(front, cter);
}
This is a late version of my code, I'm sure it was a bit better before I messed with it a bunch to try to get it to work
Thanks!
Every recursive implementation consists of two parts:
base case - that represents a simple edge-case for which the outcome is known in advance. For this task, the base case is a situation the given Node is null. Think about it this way: if a head-node is not initialed it will be null and that is the simplest edge-case that your method must be able to handle. And return value for the base case is 0.
recursive case - a part of a solution where recursive calls a made and where the main logic resides. In the recursive case, you need to check the value of a current node. If it matches the target value, then the result returned by the method will be 1 + countH(cur.next, i), otherwise it will be a result of the subsequent recursive call countH(cur.next, i).
Base case is always placed at the beginning of the method, followed by a recursive case.
And when you are writing a recursive part, one of the most important things that you have to keep in mind is which parameters change from one recursive call to another, and which remains the same. In this case, changes only a Node, the target value i remains the same.
public int count(int i) {
return countH(first, i);
}
private int countH(Node cur, int i) { // `front` replaced by `cur`
if (cur == null) { // not cur.next == null (it'll fail with exception if the head-node is null)
return 0;
}
// int cter = 0; // this intermediate variable isn't needed, it could be incremted by 1 at most during the method execution
// if(cur.item == i)
// cter++;
// return countH(cur, cter); // this line contains a mistake - variable `i` has to be passed as a parameter and `cter` must be added to the result returned by a recursive call
return cur.item == i ? 1 + countH(cur.next, i) : countH(cur.next, i);
}
Suggestion
Follow the comments in the code. I've left your original lines in place so that will be easier to compare solutions. Also, always try to come up will reasonable self-explanatory names for variables (as well as methods, classes, etc). For that reason, I renamed the parameter front to cur (short for current), because it's meant to represent any node, not first or any other particular node.
Side note
This statement is called a ternary operator or inline if statement
cur.item == i ? 1 + countH(cur.next, i) : countH(cur.next, i);
And it's just a shorter syntax for the code below:
if (cur.item == i) {
return 1 + countH(cur.next, i);
} else {
return countH(cur.next, i);
}
You could use either of these constructs in your code. The difference is only in syntax, both will get executed in precisely the same way.
In a linked list, you should have one element and from that you get the value and the next element. So your item could look like (I am omitting getters, setters and exception handling):
class Item {
Object value;
Item next;
}
Then your counter for a specific value could look like
int count(Object valueToCount, Item list) {
int result = 0;
if (valueToCount.equals(list.value)) {
result++; // count this value
}
if (value.next != null) {
result += count(valueToCount, value.next) // add the count from remainder of the list
}
return result;
}
public int count(int i) {
return countH(first, i);
}
private int countH(Node front, int i) { // TODO
if(front==null) {
return 0;
}
if (front.item == i) {
return 1 + countH(front.next, i);
} else {
return countH(front.next, i);
}
}

Recursion not working when called into another class

I wrote a recursive method which searches through a BST, compares the argument with the string property in the node, and returns the int property from that node if the strings match. The method works when it's called in it's own class, however, when I call it into a different class, it doesn't work anymore. So basically, the private part of the method works, its just the public part that's messing me up.
public int boka(String ime) {
int bobo=boka(this.root,ime);
return bobo;
}
private int boka(Node curr_root,String ime){
if(curr_root==null){
return -1;
}
boka(curr_root.left,ime);
if(curr_root.info.ime.equalsIgnoreCase(ime)) {
return curr_root.info.pobjede;
}
boka(curr_root.right,ime);
return -1;
}
So basically, the private part works, however, when I call the recursion in another class using the public, it always returns -1.
In the other class, I'm doing this:
public static void main(String[] args) {
// TODO Auto-generated method stub
BinTree bt = new BinTree();
int a = bt.boka("Djole");
I omitted the actual Node making and inserting, since I don't think that's relevant.
Your search will always return -1 because you haven't properly implemented the search. I don't know why it's working when you run it in "it's own class" but you need to return the value of the recursive call; otherwise, you are just returning -1 when the recursion is complete.
You can adjust your algorithm to this, and get it to work:
private int boka(Node curr_root,String ime){
if(curr_root.left != null) return boka(curr_root.left,ime);
if(curr_root.info.ime.equalsIgnoreCase(ime)) return curr_root.info.pobjede;
if(curr_root.right != null) return boka(curr_root.right,ime);
return -1;
}
That does not seem like searching in a Binary Search Tree (or what else BST means?), it is more like an in-order traverse of an arbitrary binary tree.
You can make it working, just do not disregard the return values in the recursion:
private int boka(Node curr_root,String ime){
if(curr_root==null) {
return -1;
}
int ret=boka(curr_root.left,ime);
if(ret!=-1) {
return ret
}
if(curr_root.info.ime.equalsIgnoreCase(ime)) {
return curr_root.info.pobjede;
}
return boka(curr_root.right,ime);
}

static and non-static difference in Kth Smallest Element in a BST

In this problem, if I make the count variable in the second line static, as shown, the kthSmallest() method computes the wrong answer. If the variable is instead made non-static then the correct answer is computed. Non-static methods can use static variables, so why is there a difference?
class Solution {
public static int count = 0;
public int res = 0;
public int kthSmallest(TreeNode root, int k) {
inorder(root,k);
return res;
}
public void inorder(TreeNode root, int k) {
if (root == null) return;
inorder(root.left,k);
count++;
if (count == k) {
res = root.val;
return;
}
inorder(root.right,k);
}
}
I see no reason why the result of a single run of your kthSmallest() method would be affected by whether count is static, but if you perform multiple runs, whether sequentially or in parallel, you will certainly have a problem. count being static means every instance of class Solution shares that variable, which you initialize once to zero, and then only increment. A second run of the method, whether on the same or a different instance of Solution, will continue with the value of count left by the previous run.
Making count non-static partially addresses that issue, by ensuring that every instance of Solution has its own count variable. You still have a problem with performing multiple kthSmallest() computations using the same instance, but you can perform one correct run per instance. If you're testing this via some automated judge then it's plausible that it indeed does create a separate instance for each test case.
But even that is not a complete solution. You still get at most one run per instance, and you're not even sure to get that if an attempt is made to perform two concurrent runs using the same instance. The fundamental problem here is that you are using instance (or class) variables to hold state specific to a single run of the kthSmallest() method.
You ought instead to use local variables of that method, communicated to other methods, if needed, via method arguments and / or return values. For example:
class Solution {
// no class or instance variables at all
public int kthSmallest(TreeNode root, int k) {
// int[1] is the simplest mutable container for an int
int[] result = new int[1];
inorder(root, k, result);
return result[0];
}
// does not need to be public:
// returns the number of nodes traversed (not necessarily the whole subtree)
int inorder(TreeNode root, int k, int[] result) {
if (root == null) {
return 0;
} else {
// nodes traversed in the subtree, plus one for the present node
int count = inorder(root.left, k, result) + 1;
if (count == k) {
result[0] = root.val;
} else {
count += inorder(root.right, k, result);
}
return count;
}
}
}

Java binary search recursive

I have to implement Binary search method which finds if value is or isn't in array. I have to use recurse.
public static boolean searchBin(int[] array, int x, int l, int r) {
int center;
center =(l+r) / 2;
if ( x > array[center] )
{
l = center+1;
}
else
{
r = center-1;
}
if ( array[center] == x )
{
return true;
}
else
{
if ( l<=r )
{
searchBin(array,x,l,r);
}
else
{
return false;
}
}
}
I'm getting the following error:
Missing return statement
Thanks.
This is because as the error suggests "not all paths return a value".
This is the possible problem:
searchBin(array,x,l,r);
A fix will be:
return searchBin(array,x,l,r);
This is because one of the possible path of execution could lead to none of your return statements: in the last if, if the condition l<=r is true, nothing is returned (you only call recursively your method).
You might want to add the return keyword before your recursive call:
return searchBin(array,x,l,r);
This way, your method will (in this case) return whatever the recursive call returns.
There is no return where you have the recursive call to
searchBin

BST size() that looks pretty

I have two functions here for size() but they both look like crap. The first one uses an overloaded function and the second, well, see for yourself. What I want to do is create a slick version of the second attempt but I'm low on ideas.
P.S: Telling me to use Java's util is kind of pointless. I want to make it pretty, not hide it.
So my function is called from a BST object and looks like this:
public int size() {
return size(root);
}
private int size(Node x) {
if (x == null) {
return 0;
} else {
return 1 + size(x.left) + size(x.right);
}
}
Now I don't want to overload the function so I rewrote it as such:
public int size() {
Node y = root;
if (y == null) {
return 0;
} else {
root = y.left;
int left = size();
root = y.right;
int right = size();
root = y;
return 1 + left + right;
}
}
All suggestions are welcome!
If it is something that is called regularly, perhaps you would be better caching the size in your Node class, and updating when you insert or delete, then it simply becomes
public int size() {
return root == null ? 0 : root.size();
}
IMHO Your first approach is good enough. Why? Because you have a perfect public interface(public size()) that governs how the size of the BST is calculated(using private size()) hiding the internal implementation. I don't see any harm in overloading as long as it lead to a better design decision.
Edit: This is my understanding of how 1st one is better than the 2nd approach. I welcome any feedbacks. Thanks!!

Categories