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

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;
}
}
}

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);
}
}

Can I use a lambda function like this?

I want to try to use lambda functions (which I do not understand well) so I can learn more about them. I have an assignment on trees that has us making a family tree class.
children is a set of all of the children nodes to this node.
/** = the number of nodes in this H1N1Tree.
* Note: If this is a leaf, the size is 1 (just the root) */
public int size() {
// TODO 2. This method must be recursive.
if (children.size() == 0) return 1;
AtomicInteger sizeOfChildren = new AtomicInteger();
children.forEach(p -> {sizeOfChildren.addAndGet(p.size());});
return sizeOfChildren.get();
}
Also as a side question, does this usage of AtomicInteger work similarly to making just an int sizeOfChildren, then running the lambda function with a C++ pointer to sizeOfChildren?
Yes you can, but it doesn't look very nice. I think I would solve it with a stream instead.
public int size() {
if (children.size() == 0) return 1;
return children.stream().mapToInt(c -> c.size()).sum();
}

Memoization of this leetcode problem. How do I memoize this recursive solution

I have made all possible swipes and then at the end I have passed the array to be checked if it is increasing or not.
this is the question and I have written the recursive approach as follows
class Solution {
public int minSwap(int[] A, int[] B) {
return helper(A,B,0,0);
}
boolean helper2(int[] A,int[] B){
for(int i=0;i<A.length-1;i++){
if(A[i]>=A[i+1] || B[i]>=B[i+1])
return false;
}
return true;
}
int helper(int[] A,int[] B,int i,int swaps){
if(i==A.length && helper2(A,B)==true)
return swaps;
if(i==A.length)
return 1000;
swap(A,B,i);
int c=helper(A,B,i+1,swaps+1);
swap(A,B,i);
int b=helper(A,B,i+1,swaps);
return Math.min(b,c);
}
private void swap(int[] A, int[] B, int index){
int temp = A[index];
A[index] = B[index];
B[index] = temp;
}
}
Here I have tried all possible swipes and then checked them and returned one with minimum swipes. How do I do memoization of this. Which variables should I use in memoization of this code. Is there any thumb rule of selecting variables for memoization?
Wikipedia says:
In computing, memoization or memoisation is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.
Since A and B don't change, the inputs are i and swaps, so for every combination of the two, we need to store the result.
One way to do this, is to use a HashMap with a key with the 2 values, e.g.
class Key {
int i;
int swaps;
// implement methods, especially equals() and hashCode()
}
You can then add the following at the beginning of helper(), though you might want to add it after the two if statements:
Key key = new Key(i, swap);
Integer cachedResult = cache.get(key);
if (cachedResult != null)
return cachedResult;
Then replace the return statement with:
int result = Math.min(b,c);
cache.put(key, result);
return result;
Whether cache is a field or a parameter being passed along is entirely up to you.

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

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.

Finding the kth to last element of a singly linked list

I have two recursive solutions to the "kth to last element of a singly linked list" problem in Java:
Solution 1:
public static Node nthToLast(Node head, int k , int i){
if (head == null) return null;
Node n = nthToLast(head.next, k, i);
i = i + 1;
if (i == k) return head;
return n;
}
Solution 2:
public class IntWrapper {
public int value = 0;
}
public static Node nthToLast(Node head, int k, IntWrapper i){
if (head == null) return null;
Node n = nthToLast(head.next, k, i);
i.value = i.value + 1;
if (i.value == k) return head;
return n;
}
The first solution returns null, while the second solution works perfectly. The first solution passes k by value, while the second solution wraps the int value in a class and passes it.
I have two questions:
Why is the first solution not working in Java? Why is pass-by-value through the local variable i in each method call not working the same as the pass-by-reference version?
The Integer class in Java wraps int, but replacing the int to Integer in the first solution does not work as well. Why?
1.
The first solution does not work because every time you pass the same value in a i variable. If you move the line i = i + ​​1 over the line Node n = nthToLast (head.next, k, i), everything should work without a problem.
2.
Integer class is immutable, so behaves like a normal int. That's why if you use an Integer in the first solution function will not work correctly. You can replace lines of code as I mentioned above that the first solution worked with an Integer.
The second solution works because the way you increment the counter does not overwrite the reference to the counting object.
In Solution 2, you're using IntWrapper to remember values across recursive invocations. Here, IntWrapper acts like a global value.
If you use local variables such as a primitive integer, you cannot preserve the incremented (i = i + 1) values across invocations. Therefore, the statement if (i == k) return head; never becomes true, unless maybe if k = 1.
Most interestingly, you cannot use Integer because Java wrapper classes are immutable in nature. The moment you do i = i + 1, a new object is created (LHS) and the old one (RHS) is thrown away/garbage collected.
In your solution 1 you should increment i before calling recursively the method. This version should work:
public static Node nthToLast(Node head, int k , int i) {
// checks empty case
if (head == null) { return null; }
// checks if current node is the solution
if (i == k) { return head; }
// else checks next node
return nthToLast(head.next, k, i+1);
}

Categories