I'm getting what I think is a spurious warning from Eclipse on the following code, used to count the number of times a given element appears in a binary tree:
public int count(E item)
{
int count = 0;
Node crnt = root;
//First seek the item in the tree
while (crnt != null)
{
int compare = crnt.data.compareTo(item);
if (compare > 0)
crnt = crnt.right;
else if (compare < 0)
crnt = crnt.left;
else
{
//Shortcut if not allowing duplicate entries
if (!allowDuplicates)
return 1;
count++;
//Duplicates are always stored to the right
while (crnt != null) // <--Warning appears here
{
crnt = crnt.right;
if (crnt.data.compareTo(item) == 0)
count++;
else
break;
}
}
}
return count;
}
(I could show you the Node class, but it's nothing surprising. Just an `E for the data and two Node pointers for left and right children.)
Am I missing something or is this a bug in Eclipse? Because it seems like it's perfectly possible, and in fact expected for crnt to be possibly null in this case, once it runs out of right children. Granted it won't be null the first time it hits this loop, but usually the IDE is smart enough to realize when the value of the variable changes within the loop. Not this time, however. Eclipse is suggesting I put a #SuppressWarnings("null") on this, or I could go into the settings and turn off this warning altogether, but I don't think it should be necessary, and I hate suppressing or ignoring warnings where they might be useful.
crnt will still be different from null because it is in the else clause of the if-elseif-else statement that might change crnt. Its value will never have changed when it hits the second while statement.
It's doing exactly as it should: telling you that the value of crnt will never be null when that code hits and that the additional check in the while unnecessary is.
Per avice by David Wallace: there is no possibility that the inner loop will be null because the crnt object is already accessed prior to that by the line int compare = crnt.data.compareTo(item);, essentially forming a prerequisite that crnt must not be null.
Related
I tried to do this LeetCode daily challenge but I've found out that my code loops infinitely.
I looked through it multiple times, but I cannot find where the problem is. If anyone could spot it, please answer.
public int longestValidParentheses(String s) {
int count, highestOne = 0, index = 0;
boolean isSevered = false;
boolean theEnd = false;
while(!theEnd) {
count = 0;
while(!isSevered) {
if(index<s.length()-2) {
if(s.charAt(index) == '(' & s.charAt(index++) == ')') {count = count + 2;index = index+2;}
else {isSevered = true;}}
else theEnd=true;isSevered=true;
}
highestOne = count;
}
return highestOne;
}
I have 2 suggestions for you:
Use indentation and do not write if/else on the same line as the code associated with them
Always, ALWAYS use bracelets, even if you have only a single command. I think one of the wrongs java did is letting the programmers the free not to use bracelets if there is just a single command after it. It confusing.
So you have 2 mistakes here that make your code run for infinity:
isSevered will always be true after one loop exactly, as you change it to true no matter what happens as it is outside the if else statements, hence the reason I wrote the 2 advices above.
You never changing isSeveres or theEnd at the outside loop. Meaning that if isSevers is true and theEnd is false, you will never enter the internal while and will never exit the outside while.
The two of those combined means that if the condition that make theEnd be initialized with true won't happen at the first run, you will be stuck with infinity loop.
I am currently building a ScapeGoatTree for a project. However I am having an issue getting my rebuild function to properly take hold of the scapegoat node it is building. In the below code you will see inside the 'if( height >alpha height)' statement 2 more if statements. The first if statement compares my scapegoat node (which I know with current test data should be the static root.left node) and it correctly says they are equal. However when I try to change the Placeholder node(Which should hopefully be an object reference to root.left) it merely overwrites my placeholder node. So thus the second if statement does not fire off, but I need the returned value of my FindScapeGoat to be the node being edited.
I am not going to lie I have always been a bit bad at understanding the pass by reference and pass by value differences in languages, but I really do need to figure out how I can properly apply changes to root.left without needing a specific call to it (since the function will not always choose root.left as the scapegoat node I need a way to call various nodes in my tree rooted at a static location).
public static void Insert(int key) {
height = dupflag = 0;
root = insertHelp(root, key);
if(dupflag == 0) MaxNodeCount++; //If inserted value wasn't duplicate increase max node count
double alphaHeight = ((Math.log(MaxNodeCount) / Math.log(1 / alpha)) + 1);
if (height > alphaHeight){
Node ToBeRebalanced = FindScapegoat(root, key); // Find scapegoat node
int sizeRoot = TreeSize(ToBeRebalanced, 0);
if(ToBeRebalanced == root.left) System.out.println("Scapegoat node == root.left");
ToBeRebalanced = RebuildTree(sizeRoot+1, ToBeRebalanced);
if(ToBeRebalanced == root.left) System.out.println("Scapegoat node == root.left");
Print(ToBeRebalanced);
Print(root);
}
}
To address the value/reference issue: non-primitive variables in Java behave (mostly, big caveat that's way out of scope for this answer) like pointers to memory locations. When you say ToBeReplaced you're changing the memory address that ToBeReplaced points to.
To your more specific issue, there are a couple of ways to handle this. The way that I would handle it would be to change the return from FindScapegoat to indicate whether the node is left or right. It seems like it's examining only the immediate children, so there's no need to return a reference to the node itself.
Something like this:
public enum Side {
LEFT,
RIGHT
}
//...
Side ToBeRebalanced = FindScapegoat(root, key); // Find scapegoat node
if (ToBeRebalanced == Side.Left){
int sizeRoot = TreeSize(root.left, 0);
root.left = RebuildTree(sizeRoot+1, root.left);
} else {
int sizeRoot = TreeSize(root.right, 0);
root.right = RebuildTree(sizeRoot+1, root.right);
}
You then could move the TreeSize call into the RebuildTree method to avoid the duplicated code.
I don't understand why I get a compile error. In my view, this method first evaluates whether n is > 0. When this is the case, then "good" will be assigned to the String object local. However, if this is not the case, then it will not do anything. Next, the method enters another decision construct. This time, it evaluates whether n <= 0. If so, it will assign "bad" to the String object.
In any of both cases, local should be initialized. However, I get a compile error, and the compiler says it may not be initialized. I do not understand where this is coming from.
Note that I know how to correct the second if by replacing it with else and removing the boolean condition. I just don't understand why in a syntax sense this is incorrect.
public class Donkey{
String s1 = "green";
public void generateReport(int n){
String local;
if(n > 0)
local = "good";
if(n <= 0)
local = "bad";
System.out.println(local);
}
The compiler has no way to 'know' that you've handled all the cases with your if statements.
Consider this example (note that the second if is just less than):
String local;
if(n > 0)
local = "good";
if(n < 0)
local = "bad";
If n = 0, then local will not get defined.
The compiler doesn't test your if statements to see if they handle all the cases while compiling.
Changing it to if/else will fix the error as you mentioned. You can also initialize the variable as other users have pointed out.
The problem is that if n is not greater than 0 and is not less or equal than 0 the var local is not initialized. So that is what the compiler is telling you.
You can solve this by initializing the local var with something.
String local = "";
The problem is solved when you use else because for the compiler there can be only 2 possible states, the one if the condition is true and the other if is not, there is no possible third state because the else contemplates all.
I keep seeing null pointer exceptions in my search method for the skip list I'm implementing.
public V find(K key, SkiplistMapNode<K,V> header, int level){
SkiplistMapNode<K,V> N = header;
for (int i = level-1; i >= 0; i--){
if ((N != null) && (N.getNext()[i] != null)){
while (N.getNext()[i].getKey().compareTo(key) < 0){
N = N.getNext()[i];
}
}
}
N = N.getNext()[0];
if ((N != null) && (N.getKey().compareTo(key) == 0)) return N.getValue();
else return null;
}
The line with the exception is:
while (N.getNext()[i].getKey().compareTo(key) < 0)
I pretty much copied this from this page though, so I'm not sure what would be wrong with it.
Supposing that N.getNext() advances to the next node, you need to memorize its value without advancing if you access the value more than once.
Same with iterator:
while (iterator.hasNext()) {
if (iterator.next()!=null) {
iterator.next().toString() // advances to the next item, which may be null
}
}
Fixed:
while (iterator.hasNext()) {
Object next=iterator.next(); // advance once
if (next!=null) { // check value
next.toString() // use same value, without advancing
}
}
It's hard to tell from your code where you really want to advance to the next element, and where you need the elements values again. Store the next value in a variable, and check and use this value afterwards, same as in the Iterator example above.
If you access an objects method, you should really make sure that the object isn't null. In your case, in...
while (N.getNext()[i].getKey().compareTo(key) < 0)
These...
N.getNext() //the only really important one you seem not to be checking
N.getNext()[i]
could be null and should be checked and possibly even (though less likely and debatably)
N
N.getNext()[i].getKey()
key
I am building a Sudoku solver that use the Try and Fail technique to solve any problem. My algorithm is:
1)Update (method that remove any possible value that already given as a final value to element in the same Row, column or squar)
2)Get the minimum element that has minimum number of possible values
3)start solve assuming the first possible value is the final value
4)save the current sate into a stack
5)Try to solve
5-a)If solved, return
5-b)if not solved and with invalid Sudoku, then Pop previous state
6)Repeat step 3) for all possible vaues (9)
7)Repeat step 2) until the puzzel is solved
This is my code
Stack<Element[][]> myStack= new Stack<>();
private Element[][] mySudoku;
public void solve(){
update();//remove all final values from all possible values for each element
if(isSudokuSolved(mySudoku)){
return;
}
//find a cell that is not confirmed and has the minimal candidates
int celli=-1,cellj=-1, p=10;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(mySudoku[i][j].getValue()==0){
if(mySudoku[i][j].getPossibleValues().size()<p){
celli=i;
cellj=j;
p=mySudoku[i][j].getPossibleValues().size();
}
}
}
}
try {
for (int c = 0; c < mySudoku[celli][cellj].getPossibleValues().size() - 1; c++) {
//save state
Element[][] copy=deepCopy(mySudoku);//copy the current state
myStack.push(copy);
//apply candidate to cell
mySudoku[celli][cellj].setValue(mySudoku[celli][cellj].getPossibleValues().get(c));
update();//check is solved
if(checkValidInputSudoku(mySudoku)){
solve();
}else{
try {
mySudoku = myStack.pop();
} catch (EmptyStackException est) {
//do nothing
}
}
}
} catch (Exception e) {
}
//if we have reached here then we are at the last possible value for the candidates so confirm candidate in cell
if(celli!=-1 && cellj!=-1 && p!=10) {//Some problems happen here "out of Boundry -1 Error"
mySudoku[celli][cellj].setValue(mySudoku[celli][cellj].getPossibleValues().get(mySudoku[celli][cellj].getPossibleValues().size()-1));
}
}//end of solve method
I have spent more than 6 hours trying to find out the problem. I have checked for the Update() method, deepCopy() method and checkValidInputSudoku() method. They all works fine. Thank you in Advance
I can see one problem in your code. You have a loop that is sawing off the branch it sits on:
for(int c = 0; c < mySudoku[celli][cellj].getPossibleValues().size() - 1; c++) {
...
mySudoku[celli][cellj].setValue(mySudoku[celli]cellj].getPossibleValues().get(c));
...
}
Apart from that, you are missing one of the values, it should be for(c=0; c!=size; ++c), i.e. not size - 1. Also, calling getPossibleValues() just once would make this code much more readable. Lastly, catching and ignoring a stack underflow is just stupid, because it hides errors in your algorithm, as far as I can tell. If you don't know how to handle an error, don't just silence it. Since java requires you to catch it, put it in the outermost place possible or at least abort or do something, but don't ignore it!
One more thing: You are recursing and passing the context data via mySodoku and myStack. This is completely missing the point of recursion (or at least the way it's typically used), because the function call stack is the only stack you need. Using these to pass parameters only makes things more complicated than necessary. Instead, the function should return a partial sodoku puzzle and return either the fully solved puzzle or null. Using is easier to distinguish than the exception you're using now, and it's a regular and expected thing, not really exceptional. Then, when trying different choices, you set the cell to the values in turn and recurse, until the call doesn't return null. If none of the choices returns a solution, you clear the cell and return null yourself.
solve(sodoku):
if sodoku is solved:
return true
if sodoku is invalid:
return false
c = some empty cell
for v in 1...9:
// set to a value and recurse
c = v
if solve(sodoku):
// found a solution
return true
// no solution found, clear cell and return failure
c = null
return false
BTW: This strategy is called "backtracking". Using a cell with the least amount of possible values is called "pruning", which allows you to cut off whole branches from the search tree. Actually determining the possible values also helps avoiding a few futile attempts.