BST size() that looks pretty - java

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!!

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

I am trying to create a circular LinkedList Please tell me if its a correct way to do it

i have implemented logic like if i am giving a index that is not yet there then it will change the index to the reminder (Same like rotated i guess ).
import java.util.LinkedList;
public class MycircularlinkedList extends LinkedList {
private static int count = 0;
public Object get(int i) {
System.out.println("count==" + count);
if (i > count) {
i = i % count;
return super.get(i);
} else {
return super.get(i);
}
}
public boolean add(Object o) {
super.add(o);
count++;
return true;
}
public void add(int i, Object o) {
if (i > count)
i = i % count;
super.add(i, o);
count++;
}
}
A couple of points I can see:
count is static, this means you're only ever going to have one number here. Probably not what you want
count is redundant, use Collection#size()
The great thing about mod (%) is that it works for all numbers, you don't need to have the conditional. 2 % 12 == 14 % 12 == -10 % 12
If you're getting rid of the count property, you can get rid of your overridden #add(Object o) logic and just do return super.add(o);
I find some problem with your code: if count ==0 and if I use the method add(7,obj) ,then 7%0 will throw ArithmeticException.count should be declared to private since you may have two instances of your class.Also,you need to check
whether poll\offerLast method satisfies your needs,since you cant restrict
any client code to avoid using them.Finally,clone\readObject\writeObject
need to be overrried to include the count variable.
You're close.
(1) The term "circular linked list" is well-known to mean a list where the tail links back to the head (and vice versa if it's a doubly-linked list). Yours is more like a "circular buffer" stored in a linked list. We could call it LinkedListCircularBuffer or something.
(2) The class should be parameterized by the element type, thus
public class LinkedListCircularBuffer<E> extends LinkedList<E> {
#Override
public E get(int i) {
return super.get(i % size()); // simpler and faster without an "if"
}
}
(3) You can call size() instead of all the code to maintain another count.
(4) Your add(int i, Object o) method doesn't support the case where i == size(), but you can fix that by not overriding add() at all.
(5) Overridden methods need the #Override annotation.
(6) It's good style to always put braces around each "then" and "else" clause. Code like
if (i > count)
i = i % count;
is fragile, e.g. adding a println() statement into that "then" clause will break it.

Whats wrong with this priority queue logic java?

I keep getting a null pointer exception when adding to this queue, especially with the percolate up. I think something is wrong with my set up but I can't figure it out. When I try to add things I get an error and my IDE says its a null pointer exception and a problem in the compare methods, making me think that the if else statements in the compare method point to a null value. I can't figure out why they would?
public class GenericHeap<E> {
int size;
int capacity = 10;
public E[] heap;
Comparator mycomparator;
public GenericHeap(Comparator c) {
heap = (E[]) new Object[capacity];
mycomparator = c;
}
public void add(E e) {
if (size == 0) {
heap[size++] = e;
} else {
heap[size++] = e;
this.percolateup(this.size);
}
}
private void percolateup(int I) {
E temp;
while (I / 2 > 0) {
if (mycomparator.compare(heap[I / 2], heap[I]) == 1) {
temp = heap[I / 2];
heap[I / 2] = heap[I];
heap[I] = temp;
}
I = I / 2;
}
}
public int compare(String t, String t1) {
if (t.length()>t1.length()){
return 1;}
else if (t.length()<t1.length()){
return -1;}
return t.compareTo(t1);
}}
You're getting your index one step ahead, to where the heap[I] is still null.
Say you are adding your 2nd item.
#entry: size==1
you go down the else path, setting heap[1]=e, THEN incrementing size to 2. You then call percolateup(2). Notice what happens when I==2 here:
if (mycomparator.compare(heap[I / 2], heap[I]) == 1) {
you access heap[2], which of course has not yet been set. NPE !
Above is definitely why you are getting the NPE...now to speculate further. I don't really understand the logic of percolateup(), but I bet the issue is you are advancing the value of size too aggressively. Possibly instead of:
heap[size++] = e;
this.percolateup(this.size);
this might help
heap[size] = e;
this.percolateup(this.size);
size++
Separately, you have a style which lends to this confusion. In add() you reference member variable size directly (size++). Nothing wrong with that; but then you turn around and access this.size. Compiler is happy but this inconsistent style is not helping your comprehension. (I personally prefer to only use "this." when absolutely required, but that's personal taste.)

Maze recursion solving StackOverflow error

I'm trying to solve a maze using recursion. It's declared Cell [][] maze.
public class Cell {
private Wall left;
private Wall right;
private Wall up;
private Wall down;
private boolean end;
// Setters and getters not shown
}
If there is no Wall for some side of the cell then it has value null, else it refers to a Wall object. Wall references are consistent: Both cells adjacent to single wall refer to it with the appropriate fields. If a wall is missing, then both adjacent cells have corresponding null entries. Here is the search:
public boolean solveMaze(Cell[][] maze, int i, int j) {
if (maze[i][j].isEnd()){
System.out.println(maze[i][j].toString());
return true;
}
if (maze[i][j].getDown() == null) {
return solveMaze(maze, i, j + 1);
}
if (maze[i][j].getUp() == null) {
return solveMaze(maze, i, j - 1) ;
}
if (maze[i][j].getLeft() == null) {
return solveMaze(maze, i - 1, j);
}
if (maze[i][j].getRight() == null) {
return solveMaze(maze, i + 1, j) ;
}
return false;
}
I'm getting a Stack Overflow error. What is wrong with my recursion stop condition?
Update:
With your highly appreciated help I solved this problem: This is correct solution which works flawless:
public boolean solveMaze(Cell[][] maze, int i, int j){
if (maze[i][j].isEnd()){
System.out.println("Maze Exit :["+i+","+j+"]" );
return true;
}
if (maze[i][j].isVisited()){
return false;
}
maze[i][j].setVisited(true);
if ((maze[i][j].getButtom() == null) ){
if (solveMaze(maze,i,j+1)==true)
return true;
}
if ((maze[i][j].getUp() == null) ){
if ( solveMaze(maze,i,j-1) ==true )
return true;
}
if ((maze[i][j].getLeft() == null)){
if (solveMaze(maze,i-1,j))
return true;
}
if ((maze[i][j].getRight() == null)){
if (solveMaze(maze,i+1,j))
return true;
}
maze[i][j].setVisited(false);
return false;
}
may be it will be helpful for any body in the future.
If the maze has a cycle, the solver can run around this cycle forever, which will cause the stack overflow you're seeing. You need a way of determining when you're seeing a maze square that's already been seen. In this case you should backtrack immediately.
This can be done either with a boolean flag visited in each cell initially set to false and then set true for each square you search, or you can maintain a separate Set of (i,j) pairs that have been searched, which is initially empty.
NB: Your use of i and j is unconventional. If someone else wrote the maze reading code with the conventional usage, this could be causing a problem. In math, i is usually used for the row number and j for the column. With this convention your wall tests do not agree with your increments and decrements. Missing the bottom wall would require you to increment i for example.
It seems to me like you're running in circles in your solver method.
I suggest you familiarize yourself with Breadth-First Search, which is often used for not too big state-search problems.
If you have some "knowledge", a heuristic, on how to search the maze then you might also take a look at A-Star Search
What BFS could do in your case is the following: (BTW, be nice and use appropriate construtors, getters and setters)
public class Cell {
public int x;
public int y;
public Cell parent;
#Override
public boolean equals(Object obj) {
// TODO Override equals so it only incudes x and y coorinates, and not parent
return true;
}
#Override
public int hashCode() {
// TODO Override hash code as well
return 0;
}
}
public Cell seachFor(Cell start, Cell finish) {
Queue<Cell> open = new LinkedList<>();
Set<Cell> closed = new HashSet<>();
open.add(start);
while (!open.isEmpty()) {
Cell current = open.poll();
if (current.equals(finish)) {
return current;
}
closed.add(current);
for (Cell neighbour : getNeighbours(current)) {
if (!closed.contains(neighbour)) {
open.add(neighbour);
}
}
}
return null;
}
private List<Cell> getNeighbours(Cell current) {
/* TODO Set the neighbour's "parent"
* Return valid adjacent neighbour cells
*/
return null;
}
public Deque<Cell> pathfinder(Cell start) {
Deque<Cell> path = new ArrayDeque<>();
path.push(start);
Cell current = start;
while (current.parent != null) {
current = current.parent;
path.push(current);
}
return path;
}
public static void main(String[] args) {
Cell start = maze.getStart();
Cell finish = maze.getFinish();
Deque<Cell> path = pathFinder(searchFor(start, finish))
while (!path.isEmpty()) {
Cell current = path.pop();
maze.moveTo(current);
}
}
Note that this is a mock code and you need to refine it before it works.
You do not have anything in your code to detect places you've already been before. If your maze contains any passages in which you can go in a circle or loop back to someplace you've been before without backtracking, it will continue to recurse down that same path infinitely.
First you go down until you reach a wall. Then, one up - then down again. And one up, and one down - until java detects that this is pretty silly and stops with a StackOverFlowError ;)
your running out of memory allocated on the stack. aka your recursion is multiply too fast where you exceed the resources of the JVM at the given time.
you can increase memory and then kill all the other iterations of this method, or change your algorithim. Changing the stacksize would be a poor solution but it may work even though your code if flawed howto increase the stacksize in eclipse I would suggest marking which areas you already visited
the maze is Cell[][] maze
public class Cell{
boolean visited = false;
Wall left;
Wall right;
Wall up;
Wall bottom;
boolean end;
//Settters and Getters
}
set that visited variable to true each time you hit it and then change your code to
public boolean solveMaze(Cell[][] maze, int i, int j){
if (maze[i][j].isEnd()){
System.out.println(maze[i][j].toString());
return true;
}
if (maze[i][j].getButton() == null)&&(maze[i][j].visited==false)){
return solveMaze(maze,i,j+1);
}
if (maze[i][j].getUp() == null){
return solveMaze(maze,i,j-1) ;
}
// ect
I wont implement it unless you have issues doing it yourself, with interview questions I think its neat if you solve them yourself with hints that way you get the feeling that you could solve something similar again, where if you just read and understand an answer you may be able to reiterate the answer to the same problem but you may not be able to come up with a novel answer to a similar problem using similar strategies.

Categories