TreeNode Method isEmpty - java

For WebCat (an automated grader) for my class I have been working with TreeNodes and it checked my work but it highlighted the return line red and said "Not all possibilities for this line were tested" for the following code:
public boolean isEmpty()
{
return root.val == null && root.rkid == null && root.lkid == null;
}
Does this mean that I must test true and false combinations (eight different tests) for this one line of code?
Is there a simpler return statement? (given a value, a left child, and a right child)
I have been working hard on this assignment for hours and hours, please help!

Related

Two versions of counting leaves in a Tree

What's the difference between these two versions?
public static int countLeaves(IntTreeNode root) {
if (root == null) {
return 0;
} else
return 1 + countLeaves(root.left) + countLeaves(root.right);
}
public static int countLeaves(IntTreeNode root) {
if (root == null) {
return 0;
} else if (root.left == null && root.right == null) {
return 1;
} else
return countLeaves(root.left) + countLeaves(root.right);
}
I couldn't find anything that use the first version in the internet.
Is the first version wrong?
I have tried to trace them on paper, they seem to be the same.
But I just want to be sure.
The first seems to count all nodes in a tree, whereas the second one one counts all leafs.
Indeed in the first one, the recursion stops when there is no valid tree anymore (root == null) and it always goes into recursion checking the left and right tree by adding 1 (for the current node).
The second only counts the leafs using the condition if (root.left == null && root.right == null).
That's assuming a leaf is identified as node that has a null root.left and a null root.right.
The first version is not counting leaves - it's counting nodes.
The second version is indeed counting leaves.
These methods will not return the same result, here's an example:
root(5)
/ \
leaf(3) leaf(7)
for such a tree the first method will return 3 (number of nodes) and the second one will return 2 (number of leafs).

Find out value that returns true from if statement -algorithm

Another class is going to pass in random numbers into this method(x,y,z). I want to know the boolean that does returns true from my last if() statement, so I can do operations on it. I have explained my logic in the comments.
I am still really new to this, so my logic may be wrong.
public static String FindDate(int x, int y, int z) {
boolean istrue1 =(x >= 1 && x <= 31);
boolean istrue2 =(y >= 1 && y <= 31);
boolean istrue3 =(z >= 1 && z <= 31);
if(istrue1 ^ istrue2){
if(istrue1^istrue3){
if(istrue2^istrue3){//now knowing that no values are the same, i can find the true value.
if(istrue1||istrue2||istrue3){
// I want to store/use/print/know which bool(istrue) that evaluated to true, so I would know if it is
//x,y,z that went through the algorithm successfully.
}
} else{return "Ambiguous";}
}else{return "Ambiguous";}
}else{return "Ambiguous";}
return "true"; //I would actually end up returning the value that went through the algorithm
}
You can store boolean values just like any other type in Java. I'm not sure exactly what your last comment means by "the value that went through", but if you want to keep track of the result of a particular test, you don't necessarily need to write something like
if (a == b) {
return true;
} else {
return false;
}
In that case,
return a == b;
is equivalent. If the expression is more complicated parens are a good idea.
return ((a == b) || c);
And instead of returning, you could always store the result and do something with it later.
bool test = ((a == b) || c);
action(test);
You can your following: But your condition is incorrect 3 variable for two value (true, false) all can't be different. So your logic always return "Ambiguous"
if(istrue1 ^ istrue2){
if(istrue1^istrue3){
if(istrue2^istrue3){
//now knowing that no values are the same, i can find the true value.
if(istrue1||istrue2||istrue3){
// I want to store/use/print/know the bool that evaluated to true, so I would know if it is
//x,y,z that went through the algorithm successfully.
return "true";
}
}
return "Ambiguous";
Instead of:
if(istrue1||istrue2||istrue3)
Its is easiest to just break it down into 3 differnt if statement.
if(istrue1)
if(istrue2)
if(istrue3)
No easy trick that i was hoping for. sad day.
Also the statements i did with the xor(^) operators turns out to be bad logic.
it would be easiest to this:
if(a&&b || a&&c || b&&c)
That would return ambiguous if any combo are both true.
However thats not the original question, but I thought i might as well mention it.

Wrap Around Grid - errors on east/west only

I have four methods that check whether or not a given grid location is next to an occupied location (value of 1). The grid is assumed to wrap around, ie, if in a 50x50 grid[0][1] is the given location and grid[49][1] is occupied, the method should return true/ My checkNorth and checkEast method are working fine, but I get an ArrayIndexOutofBoundsException: -1 error for either the south or west methods every time I run the program. I checked my math and I think it should work - am I using the modulo incorrectly, or am I missing something else?
EDIT: Clarified the wrapping criterion, word use correction.
boolean checkWest(int indexA, int indexB)
{
if (indexA-1 > 0)
{
if (grid[indexA-1][indexB] == 1)
{
return true;
}
}
if (indexA-1 < 0)
{
if (grid[(indexA-1)%width][indexB] == 1)
{return true;}
else return false;
}
return false;
}
I see a couple problems. First, Java arrays are zero-indexed, which means that the first element is at index 0. So it's okay to check grid[indexA-1][indexB] when indexA-1 is equal to 0. Second, you're not properly handling when indexA equals 0. Here is my implementation. I also simplified the logic a bit.
boolean checkWest(int indexA, int indexB)
{
if (indexA > 0)
return grid[indexA - 1][indexB] == 1;
else
return grid[width + indexA - 2][indexB] == 1;
}
EDIT: I'm pretty sure I butchered the math with the second return statement. It should be right now...

Recursion related to trees

Here's code which finds a root-to-leaf path that equals to a particular sum:
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
if (root.left==null && root.right==null) {
return (sum == root.val);
}
return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
Even when one recursive call returns true (with return (sum==root.val)), I don't understand how the original function call is true.
My understanding is that in the stack, that particular activation record is true, but then wouldn't the other calls on the stack return false; clearly the remaining might not be a path, and wouldn't that render it all as false? How does it attach importance to that if statement?
This is actually not coded in the clearest manner.
Recursion is always about solving a problem by using the same procedure (function) to solve one or more smaller versions of the same problem, then combining these solutions.
In this case, the smaller problems are to check for the rest of the required sum in the left and right subtrees (if they exist).
We can stop after the left if successful, skipping the right. In this manner, the "leftmost" path in the tree with the desired sum is found. We have no need to find any others.
When checking a subtree, we subtract the value of the current node from the desired sum. Intuitively this is making the problem "smaller" as described above.
I'll add comments that show the logic.
public boolean hasPathSum(TreeNode root, int sum) {
// If we've reached a null child, the other child is non-null, so we're
// not at a leaf, so there no way this can be a leaf-to-path sum.
// See below for why this is the case.
if (root == null) {
return false;
}
// If we're at a leaf (null children), then we've found the path
// if and only if the node value exactly equals the sum we're looking for.
if (root.left == null && root.right == null) {
return (sum == root.val);
}
// We're not at a leaf. See if we can find the remaining part of the sum
// by searching the children. Null children are handled above. If the
// sum is found in the left subtree, the short-circuit evaluation of ||
// will skip searching the right.
return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
}
Note that it possibly doesn't make sense that
hasPathSum(null, 0)
returns false in this code. I'd do it this way:
class TreeNode {
// ... skipping other TreeNode fields.
public boolean isLeaf() { return left == null && right == null; }
public boolean hasPathSum(int sum) {
return isLeaf() ? sum == val :
(left != null && left.hasPathSum(sum - val)) ||
(right != null && right.hasPathSum(sum - val);
}
}
Here is a good visualisation for recursion. Basically, when you call hasPathSum it 1st checks if root is null. If it's null, then it will return with a false.
If root is not null, then it goes further. if left and right both nulls then you are at a leaf node. If the leaf node has the same value as the root, then you'll return with true. Otherwise it will be a false.
If both if statements were skipped it means, that either the left, or the right (or both) has more nodes. Then the root node will become the your left and right, and you'll check for the sum value there, and return with the result from them.
Let's assume that this is your tree and the leaf4 has the desired value:
root
left right
leaf1 - leaf3 leaf4
----------- 1st depth, with root node ---------------
hasPathSum(root)
root==null //false, so it moves on
root.left // is 'left', so skipping
hasPathSum(left) || hasPathSum(right) // this statement will be evaluated
------------- 2nd depth, with left node ---------------
hasPathSum(left)
left==null //false, so it moves on
left.left // is 'leaf1', so skipping
hasPathSum(leaf) || hasPathSum(null) // this statement will be evaluated
------------- 3rd depth, with leaf1 node ---------------
hasPathSum(leaf1)
leaf1==null //false, so it moves on
leaf1.left and leaf1.right // are both null, so returnin with sum == root.val
------------- 3rd depth, with - node ---------------
hasPathSum(-)
-==null //true, so it returns with false
------------- 2nd depth, with left node ---------------
false || false // is false, so it will return with false
------ in this moment, hasPathSum(left) part of 1st depth's has been evaulated to false
so hasPathSum(right) has to be ecaluated as well.
It wont be any different from the code above, except that when processing leaf4, the sum==root.val will be true, so the whole thing will return true. Hope this helps.
A simple example explained might help.
Let's consider a tree like this:
5
/ \
2 3
\
1
And we're looking for a sum of 9.
Now the recursive calls will look like this:
(my indentation is such that each statement is executed by the function at the previous level of indentation)
hasPathSum(N5, 9)
hasPathSum(N2, 9-5 = 4)
return false // since 2 != 4
hasPathSum(N3, 9-5 = 4)
hasPathSum(null, 4-3 = 1) // left child of N3
return false // since root == null
hasPathSum(N1, 4-3 = 1)
return true // since 1 == 1
return (false || true) = true
return (false || true) = true

Sudoku Solver brute force algorithm

Still working on my sudoku solver, I have once again run into some trouble. I have gotten the sudoku solver to work, however whenever I attempt to solve a really "hard" sudoku board, my solver tells me there are no possible solutions, due to a stack overflow error. And yes, I know for a fact that these boards DO have a solution.
I am using the brute force algorithm -- I start at square one (or [0][0] if you prefer) and insert the first legal value. I then do a recursive call to the next square, and so on. If my function has not gone through the entire board, and finds there are no possible legal values, it moves to the previous square and attempts to increment the value there. If that fails, it moves further back. If it ends up at square one with no possible solutions, it exits.
I admit my code is not pretty and probably quite inefftective, but please keep in mind that I am a first year student trying to do my best. I don't mind comments on how to effectivize my code though :)
For squares without a final predefined number, here's the solver function:
public void fillRemainderOfBoard(Square sender){
try {
while(true){
if(currentPos > boardDimension){
if(previous != null){
this.setNumrep(-1);
this.setCurrentPos(1);
previous.setCurrentPos(previous.getCurrentPos()+1);
previous.fillRemainderOfBoard(this);
return;
} else if(sender == this){
this.setCurrentPos(1);
} else {
break;
}
}
if((thisBox.hasNumber(currentPos)) || (thisRow.hasNumber(currentPos)) || (thisColumn.hasNumber(currentPos))){
currentPos++;
} else {
this.setNumrep(currentPos);
currentPos++;
break;
}
}
if(this != last){
next.setNumrep(-1);
next.fillRemainderOfBoard(this);
} else {
return;
}
} catch (StackOverflowError e){
return;
}
}
In my code, the numrep value is the value that the square represents on the board. The currentPos variable is a counter that starts at 1 and increments until it reaches a legal value for the square to represent.
For squares with a predefined number, here's the same function:
public void fillRemainderOfBoard(Square sender){
if((sender.equals(this) || sender.equals(previous)) && this != last){
System.out.println(next);
next.fillRemainderOfBoard(this);
} else if (sender.equals(next) && this != first) {
previous.fillRemainderOfBoard(this);
} else {
System.out.println("No possible solutions for this board.");
}
}
Now, my problem is, like I said, that the function DOES solve sudokus very well. Easy ones. The tricky sudokus, like those with many predefined numbers and only a single solution, just makes my program go into a stack overflow and tell me there are no possible solutions. I assume this indicates I am missing something in the terms of memory management, or the program duplicating objects which I call in my recursive functions, but I do not know how to fix them.
Any help is greatly appreciated! Feel free to pick on my code too; I'm still learning (oh, aren't we always?).
___________________EDIT________________
Thanks to Piotr who came up with the good idea of backtracking, I have rewritten my code. However, I still cannot get it to solve any sudoku at all. Even with an empty board, it gets to square number 39, and then returns false all the way back. Here is my current code:
public boolean fillInnRemainingOfBoard(Square sender){
if(this instanceof SquarePredef && next != null){
return next.fillInnRemainingOfBoard(this);
} else if (this instanceof SquarePredef && next == null){
return true;
}
if(this instanceof SquareNoPredef){
currentPos = 1;
if(next != null){
System.out.println(this.index);
for(; currentPos <= boardDimension; currentPos++){
if((thisBox.hasNumber(currentPos)) || (thisRow.hasNumber(currentPos)) || (thisColumn.hasNumber(currentPos))){
continue;
} else {
System.out.println("Box has " + currentPos + "? " + thisBox.hasNumber(currentPos));
this.setNumrep(currentPos);
System.out.println("Got here, square " + index + " i: " + numrep);
}
if(next != null && next.fillInnRemainingOfBoard(this)){
System.out.println("Returnerer true");
return true;
} else {
}
}
}
if(next == null){
return true;
}
}
System.out.println("Returning false. Square: " + index + " currentPos: " + currentPos);
return false;
}
I had to complicate things a bit because I needed to check whether the current object is the last. Hence the additional if tests. Oh, and the reason I am using boardDimension is because this sudoku solver will solve any sudoku -- not just those 9 by 9 sudokus :)
Can you spot my error? Any help is appreciated!
So your problem lies here:
previous.fillRemainderOfBoard(this);
and here
next.fillRemainderOfBoard(this);
Basically you have too many function calls on the stack because you are going forward and backward multiple times. You are not really returning from any call before answer is found (or you get StackOverflowError :)). Instead of increasing stack size by using recursive function try to think how to solve problem using a loop (pretty much always loop is better than recursive solution performance wise).
Ok so you can do something like this (pseudo code):
boolean fillRemainderOfBoard(Square sender){
if (num_defined_on_start) {
return next.fillRemainderOfBoard(this);
} else {
for (i = 1; i < 9; ++i) {
if (setting i a legal_move)
this.setCurrentPos(i);
else
continue;
if (next.fillRemainderOfBoard(this))
return true;
}
return false;
}
The stack size will be ~81.

Categories