Binary Search Tree method prints oddly with some words - java

Binary Search Tree:
[1]: https://i.stack.imgur.com/lrhxx.png
void wordsAtDepth() {
int depth = 0;
int numOfNodes;
Queue queue = new Queue(32); // Make a new Queue called queue.
queue.insert(root); // Insert the root into the queue
// While queue is not empty we will continue the while loop
while (!queue.isEmpty()) {
// numOfNodes keeps track of how many times we are going to
// continue the for loop in the current while loop.
numOfNodes = (int) Math.pow(2, depth);
// for loop will continue until i is equal to or is greater
// than numOfNodes.
for (int i = 0; i < numOfNodes; i++) {
// Current will equal to the removed element from the
// queue.
Node Current = queue.remove();
// If Current does not equal null then print current
// and insert its' left and right child.
// If Current does equal null then do nothing go to the
// next iteration of the for loop
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
}
}
// Makes new line every time we finish the while loop.
// Which means new line for the next iteration of the
// while loop to separate the different depths.
System.out.println(" ");
depth++;
}
}
Using OPTIMAL, OUTPUT:
O
IP
AMT
L
This is correct, but if I use a word like SUPERMAN:
S
PU
ER
AMN
SPUERAMNPUERAMN
ERAMNAMNNEMNNAMNN
AMNNNNAMNNNNNNNN
NNNNNNNN
I really want to use the numOfNodes = (int) Math.pow(2, depth);, since the number of nodes at a certain depth is 2^Depth. But it seems to not work.
I have a working version of this code where I use numOfNodes = queue.size(), but that is not what I want to use.

Related

Display Nodes at the same depth not working

void wordsAtDepth() {
int depth = 0;
int numOfNodes;
Queue queue = new Queue(32); // Make a new Queue called queue.
queue.insert(root); // Insert the root into the queue
// While queue is not empty we will continue the while loop
while (!queue.isEmpty()) {
// numOfNodes keeps track of how many times we are going to
// continue the for loop in the current while loop.
numOfNodes = (int) Math.pow(2, depth);
// for loop will continue until i is equal to or is greater
// than numOfNodes.
for (int i = 0; i < numOfNodes; i++) {
// Current will equal to the removed element from the
// queue.
Node Current = queue.remove();
// If Current does not equal null then print current
// and insert its' left and right child.
// If Current does equal null then do nothing go to the
// next iteration of the for loop
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
}
}
// Makes new line every time we finish the while loop.
// Which means new line for the next iteration of the
// while loop to separate the different depths.
System.out.println(" ");
depth++;
}
}
Nodes contain char values. For the word OPTIMAl it prints correctly, but for words like HAPPY or SUPERMAN they print incorrectly. For example: SUPERMAN: S PU ER AMN SPUERAMNPUERAMN ERAMNAMNNEMNNAMNN AMNNNNAMNNNNNNNN NNNNNNNN
Instead of using numOfNodes = (int) Math.pow(2, depth); the code works when I use the numOfNodes = queue.length(). But I WANT to use numOfNodes = (int) Math.pow(2, depth); since the for loop will should loop for the ammount of Nodes at a depth. Since the number of Nodes in a depth is 2^Depth.
If you expect the number of nodes at a certain depth to be that power of 2, then you must make sure to deal with the case where your tree is not perfect, because then -- even if your tree is complete -- the bottom level will not be fully filled.
The simple fix seems to be that you always add 2 entries to the queue for every entry you pop from it. So change this:
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
}
to this:
if(Current != null){
System.out.print(Current.cData);
queue.insert(Current.leftChild);
queue.insert(Current.rightChild);
} else {
queue.insert(null);
queue.insert(null);
}

How to shift element in an Arraylist to the right in java

So I am trying to create a method that shifts all of the elements in an arraylist to the right and the last element will become the first element. When I run the code, I am told I have an out of bounds error. Here is what I have so far:
public void shiftRight()
{
//make temp variable to hold last element
int temp = listValues.get(listValues.size()-1);
//make a loop to run through the array list
for(int i = listValues.size()-1; i >= 0; i--)
{
//set the last element to the value of the 2nd to last element
listValues.set(listValues.get(i),listValues.get(i-1));
//set the first element to be the last element
listValues.set(0, temp);
}
}
Maybe this is an exercise you are working on, but the ArrayList.add(int index,E element) method does almost what you want.
"Inserts the specified element at the specified position in this list. Shifts the element currently at that position (if any) and any subsequent elements to the right (adds one to their indices)." (italics added)
So just add the last element in the list at position 0. And delete it from the end.
A few problems here:
Your for loop condition needs to exclude the zeroth element so it should be i > 0 otherwise you'll get to the point where you want to put element at position -1 to position 0 resulting in out of bounds error.
Setting the first element to be the last should be outside the loop.
listValues.set takes in an index in the list as the first parameter, you are giving it the object in the list
public void shiftRight()
{
//make temp variable to hold last element
int temp = listValues.get(listValues.size()-1);
//make a loop to run through the array list
for(int i = listValues.size()-1; i > 0; i--)
{
//set the last element to the value of the 2nd to last element
listValues.set(i,listValues.get(i-1));
}
//set the first element to be the last element
listValues.set(0, temp);
}
The easiest and shortest solution : (if you don't have concurrent use of list - Because in concurrent use and iterating on it, the list size should not change, otherwise you get ConcurrentModificationException)
public void shiftOneToRight() {
listValues.add(0, listValues.remove(listValues.size() - 1));
}
Here is the simplest solution
Collections.rotate(list, rotationPosition);
my code to put a number in the right place in a List
int nr = 5; // just a test number
boolean foundPlace = false;
for(int i = 0; i < integerList.size(); i++){
if(nr <= integerList.get(i)){
integerList.add(i,nr);
foundPlace = true;
break;
}
}
if (!foundPlace)
integerList.add(integerList.size(), nr);
as the guy above said, "integerList.add(element)" inserts the specified element at the specified position in this list. Shifts the element currently...
input array list: locationMap
shift LHS elements from idxStart in circular way
shifted output list: extendedList
// make extended list to behave like circular
List<String> extendedList = new ArrayList<>();
for (int i = idxStart; i < locationMap.size(); i++) { // current to end
extendedList.add(locationMap.get(i));
}
for (int i = 0; i < idxStart; i++) { // 0 to current
extendedList.add(locationMap.get(i));
}

Inserting into an ArrayList<Occurrence> using Binary Search

So this method is passed an arraylist of Occurences, which each contain a string and a frequency. The frequency is the only important part here. But what I need to do is use binary search to insert the last element in the arraylist into the sorted position. Every time I run this code, the insertion position is printed as -1. Am I missing something in my code?
I need to keep track of the indexes in the array I hit during binary search, which shouldn't be too difficult, but explains the return type.
public ArrayList<Integer> insertLastOccurrence(ArrayList<Occurrence> occs) {
ArrayList<Integer> path = new ArrayList<Integer>();
int targetFreq = occs.get(occs.size()-1).frequency; //gets the frequency of the thing we want to insert
//if the array is just 1 value, don't do anything
if(occs.size() == 1){
return null;
}
int start = 0; // The start of the search region
int end = occs.size()-2;// The end of the search region is 1 less than the last position
int position = -1; // Position of the target
// While there is still something list left to search and
// the element has not been found
while (start <= end && position == -1) {
int mid = start + (end - start) / 2; //int mid = (start + end) / 2; // Location of the middle
// Determine whether the target is smaller than, greater than,
// or equal to the middle element
if (targetFreq < occs.get(mid).frequency) {
// Target is smaller; continue the left half
end = mid - 1;
}
else if (targetFreq > occs.get(mid).frequency) {
// Target is larger, continue the right half
start = mid + 1;
}
else {
// Found it!
position = mid;
}
}
System.out.println(position);
return path;
}
So, do I understand this right? You have an ArrayList that is sorted with the exception of the last element (at size()-1) and you want to find the index this element has to be inserted after to regain the sorted property?
I suppose, with the presented code, such an index is only found if the ArrayList contains another element that equals the last (to be inserted) one because position is only set to mid if targetFreq equals the frequency of one of considered elements. Since the last element is never considered (end = size()-2) it is very likely that no equal element is found.

Unexpected Java performance

I have just thrown everything I know about Java optimisation out the window. I have the following task:
Given a 2D array representing a playing field and a position on the field, fill another array with the number of steps a player can make to get to every other position in the field. The player can move up, down, left and right. For example, the first neighbours will be all 1's, with the diagonals being all 2's.
For the first attempt, I tried a simple 4-way floodfill algorithm. It wad dreadfully slow.
Secondly, I decided to get rid of the recursion and use a simple Queue. It worked lovely and gave a huge speed-up (very roughly 20x). Here is the code:
private void fillCounterArray(int[] counters, int position) {
Queue<Integer> queue = new ArrayDeque<Integer>(900);
// Obtain the possible destinations from position, check the valid ones
// and add it the stack.
int[] destination = board.getPossibleDestinations(position);
for (int i = 0; i < destination.length; i++) {
if (board.getBoard()[destination[i]] == Board.CLEAR) {
counters[destination[i]] = 1;
queue.add(destination[i]);
}
}
// Now fill up the space.
while (!queue.isEmpty()) {
int pos = queue.remove();
int steps = counters[pos];
destination = board.getPossibleDestinations(pos);
for (int i = 0; i < destination.length; i++) {
int dest = destination[i];
if (board.getBoard()[dest] == Board.CLEAR && (counters[dest] > steps + 1 || counters[dest] == 0)) {
counters[dest] = steps + 1;
queue.add(dest);
}
}
}
}
Now, "common-sense" told me that the queue operations with a static array and an int-pointer would be faster. So I removed the Queue and use a standard int[] array. The code is identical, except for the queue-like operations. It now looks like this (As you can see, I use to live by the C-side :)):
private void fillCounterArray(int[] counters, int position) {
// Array and its pointer.
int[] queue = new int[900]; // max size of field
int head = 0;
// Obtain the possible destinations from position, check the valid ones
// and add it the stack.
int[] destination = board.getPossibleDestinations(position);
for (int i = 0; i < destination.length; i++) {
if (board.getBoard()[destination[i]] == Board.CLEAR) {
counters[destination[i]] = 1;
queue[head++] = dest[i];
}
}
// Now fill up the space.
while (head > 0) {
int pos = queue[--head];
int steps = counters[pos];
destination = board.getPossibleDestinations(pos);
for (int i = 0; i < destination.length; i++) {
int dest = destination[i];
if (board.getBoard()[dest] == Board.CLEAR && (counters[dest] > steps + 1 || counters[dest] == 0)) {
counters[dest] = steps + 1;
queue[head++] = dest;
}
}
}
}
When I ran this "optimised code" it was significantly slower than using the Queue and only about twice as fast as the recursive technique. There is also hardly any difference when I declare the array as an instance variable. How is this possible?
Your reversed the order while optimising I think;
The queue is fifo, first in first out
The array is lifo, last in first out, as you walk it downwards
That will usually give you different performance ;-)
Insert two Counters in each Loop one in the for loop and one in the while loop in both versions, compare the numbers you get at the end, how many rounds do you make in each version, if you have another Loop in getPossibleDestination then log the pos variable too.
I guess that would be a good starting point to figure it out.
Another way would be to print the time difference on different lines in your program, let say before the 1st loop, between both and at the end, once you compare results and know where it takes a long time in the second Version you can print timestamps in the loop on different lines.

N-Queens in Java using Stacks, Keeps taking the same route after backtracking

Title pretty much says it all. I've been working on this and just can't figure out a way to prevent it from happening. Perhaps some way to store invalid placements? Or how would I implement a way for it to 'resume' from the last time it was at this row so it doesn't just pick the same value again?
Ignore the while i, its just for debugging. Same with the prints.
import java.util.Stack;
public class NQueens {
//***** fill in your code here *****
//feel free to add additional methods as necessary
//finds and prints out all solutions to the n-queens problem
public static int solve(int n) {
//***** fill in your code here *****
//Scaffolding code from Stacks.pdf
//------------------------------------------------------------------------------------------------------------------
// Create empty stack and set current position to 0
Stack<Integer> s = new Stack<Integer>();
int column = 0;
int row = 0;
int solutionsCount = 0;
int i = 0;
//Repeat {
//loop from current position to the last position until a valid position is found //current row
while (i < 5){
for(column = 0; column < n ;column++) {
//if there is a valid position
System.out.println("Top of for loop");
System.out.println("Column/index for = " + column + "; Row is: " + row);
System.out.println("Stack size = " + s.size());
System.out.println();
if (isValid(s, column, row)) {
s.push(column);
//push the position to stack, set current position to 0 // move to next ro
row++;
column = 0;
}//if
}//for
//if there is no valid position
if(!isValid(s, column, row) || column >= n){
//if stack is empty, break // stop search
if(s.size() == 0){
break; //stop search
}//if
//else pop from stack, set current position to next position // backtracking to previous row
else{
s.pop();
column++;
row--;
}//else
}//if
//if stack has size N { // a solution is found
if (s.size() == n){
solutionsCount++;
printSolution(s);
//pop from stack, set current position to next position // backtracking to find next solution
s.pop();
row--;
column++;
}//if
else {
}//else
i++;
// Make sure to change this when not bug testing for 4x4
}//end for loop
//update the following statement to return the number of solutions found
return solutionsCount;
}//solve()
This looks like homework, so here are some pointers:
You are modifying the column variable after the for loop. Obviously, you intend its value to carry over into the next iteration of while. But then the first thing you do when while starts again is you set column to 0 with for (column = 0; ....), which overrides its value. What information is column supposed to carry from one iteration of while to the next?
You are setting column to 0 inside the for loop but it will be incremented to 1 with column++ before the next for iteration.
You are using column in the if statement immediately after the loop. What do you expect the value of that variable to be after the for loop completes?
After the for loop you have two if statements that are trying to check for the same condition -- whether the for loop found a solution. Only the second if is much clearer about it. Do you even need both ifs?
You are putting column values into the stack, but when you pop them off the stack, you just discard them. Don't you have some use for these values?

Categories

Resources