Recursion reverse a SingleLinkedList and print as a String - java

I was given the task to add a method reversed to a SingleLinkedList using recursion preferably.
public String reversed() {
StringBuilder b = new StringBuilder();
reversed(first, b);
return b.toString();
}
private void reversed(Node<E> n, StringBuilder b) {
if (n != null) {
reversed(n.next, b);
b.append(n.element);
b.append(ā€™\nā€™);
}
}
Seems to work very well when I test in eclipse.
However, I am not sure if I understand 100% why.
This is how I think. Let us imagine we have SingleLinkedList with 5 Nodes and we put in the first Node in the private method to reverse it.
Since n isnt null, its the first node. It will enter the if statement.
It will call on itself, but now with Node second, its not null since it will repeat....
Now it reaches Node 5, it calls itself, but then it will call on reversed (six,b) since Node six dosent exist and is null, it will not work. Therefore it moves to the row "b.append(n.element);" however. It now remembers where it started and appends "first.element"; after that it will append a new row.
What exaplins the logic that it will hereafter append second.element; Can someone explain how I should think to understand that it will now append the second element?
Thanks in advance, think I really need to understand this to under recursion fully in java

Each method call keeps its own state. Once you get to node 6, there will be 5 calls on the stack waiting for reversed(n.next, b) to finish. Each method can only continue after the call to reversed on the stack above it finishes.
In this example you have last in as the first to act, i.e. you have a non-tail recursive function (the recursive call is happening before you perform the action of that method).
Imagine if every time you got to reversed you replaced that method call with the code it would execute. Remember all the calls happens serially (there is only one thread, nothing can happen in parallel). You'd get something that looks like this:
if (n0 != null) {
Node<E> n1 = n0.next;
if (n1 != null) {
Node<E> n2 = n1.next;
if (n2 != null) {
Node<E> n3 = n2.next;
if (n3 != null) {
Node<E> n4 = n3.next;
if (n4 != null) {
Node<E> n5 = n4.next;
if (n5 != null) {
// would be null so nothing happens
}
b.append(n4.element);
b.append('\n');
}
b.append(n3.element);
b.append('\n');
}
b.append(n2.element);
b.append('\n');
}
b.append(n1.element);
b.append('\n');
}
b.append(n0.element);
b.append('\n');
}
You can see how this code gets pretty hard to read once the number of elements goes up. When we don't know exactly how long the list will be this approach breaks down... you wouldn't want to do this 10, 100, or possibly thousands of times!
This is exactly why recursion is so useful for applications like this. We are able to re-use the interesting logic without having to know the length of the list, and are able to reduce duplicated code significantly.
Just keep in mind that recursion comes at a memory cost. Each time you enter the recursive method you add state to the stack. Once you cap out the memory on your machine you'll have to begin looking at non recursive ways of performing this work.

Related

How do I recursively append two linked lists in Java? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
So basically my code iterates through the list and the original method is supposed to return the linked list however it doesn't seem to be adding the nodes that I link in the recursive method and I'm confused as to why. Can anyone help me?
// Append MyStringBuilder2 b to the end of the current MyStringBuilder2, and
// return the current MyStringBuilder2. Be careful for special cases!
public MyStringBuilder2 append(MyStringBuilder2 b)
{
//Test if Invalid
if(b.firstC==null){
return this;
}
//Test if condition is met
else {
CNode lastNode =firstC;
recurseAppendBuild(lastNode, b);
return this;
}
}
private void recurseAppendBuild(CNode lastNode, MyStringBuilder2 BPoint) {
//Test if all nodes have been added
if(lastNode.next==null&&BPoint.firstC==null) {
System.out.println("finished");
}
//Tests if all nodes in the original linked list have been passed through
else if(lastNode.next==null) {
lastNode.next= new CNode(BPoint.firstC.data);
BPoint.firstC=BPoint.firstC.next;
recurseAppendBuild(lastNode.next, BPoint);
}
//Recurse until condition is met
else {
recurseAppendBuild(lastNode.next, BPoint);
}
}
```
Okay, your code needs some work. Let's look at your first method. I'm going to rewrite it.
public MyStringBuilder2 append(MyStringBuilder2 fromBuilder)
{
if (fromBuilder.firstC != null) {
recurseAppendBuild(fromBuilder.firstC);
}
return this;
}
I changed a number of things.
I used a more meaningful name on the argument. It's a good idea to give your variables meaningful names, not just 'b'. Note that I never use one-character names. If nothing else, it can be really hard to search on that. If you do "int i" and then search for i, you'll get a LOT of hits that aren't i at all.
This is a very trivial thing and doesn't affect the quality of your code.
In all cases, you always return yourself, so the return statement can be after the if-else structure, which is easier to see that it's the same.
That eliminates the top if-block entirely, so I reversed the logic.
And I changed the method signature of your recursive method, for reasons I'll describe below.
The end result is short and sweet and easily understood.
Now, let's look at your second method:
private void recurseAppendBuild(CNode lastNode, MyStringBuilder2 BPoint) {
//Test if all nodes have been added
if(lastNode.next==null&&BPoint.firstC==null) {
System.out.println("finished");
}
//Tests if all nodes in the original linked list have been passed through
else if(lastNode.next==null) {
lastNode.next= new CNode(BPoint.firstC.data);
BPoint.firstC=BPoint.firstC.next;
recurseAppendBuild(lastNode.next, BPoint);
}
//Recurse until condition is met
else {
recurseAppendBuild(lastNode.next, BPoint);
}
}
Your variable named BPoint breaks JAVA naming standards. It should start with a lower case letter.
If you pass in a MyStringBuilder2 as the second argument, then as you move things from BPoint to the end of your list and recurse, you have to remove them from BPoint, which is a pain in the ass. So instead, I didn't point to the wrapper. In my code above, I passed in the head of the list (fromBuilder.firstC).
You are finished when your list-to-append-from (BPoint) is empty, not when lastNode is null. Your first if is flawed.
You aren't recursively adding items. You're recursively looking for the end of the list. I don't think that's what you really want.
You're messing up the integrity of BPoint. You're making a copy of the nodes as you add them, but you're then dropping the old ones from BPoint but NOT maintaining lastC at all.
And you have a significant problem if your list starts as empty, as firstC and lastNode will both be empty.
So let's think about it this way. First, doing this recursively is silly, but that's the assignment, so we'll work with it.
A recursive definition is:
AppendedList = OriginalList + firstItem + Append Tail of List.
private void recurseAppendBuild(CNode headToAppend) {
if (headToAppend == NULL) {
// All done.
return;
}
CNode nodeToAppend = new CNode(headToAppend.data);
if (lastC == nullptr) {
// Original list is empty.
firstC = lastC = nodeToAppend;
else {
lastC.next = nodeToAppend;
lastC = nodeToAppend; // Point the tail at the new tail
}
// And here you recurse, always.
recurseAppendBuild(headToAppend.next);
}
Let's look at this.
I'm assuming you keep both a firstC and lastC in your builder. It would be deeply inefficient otherwise. So you only need to pass in the chain of nodes, not the surrounding wrapper.
By putting a null-check at the top of this method, you eliminate other null checks. Note -- this means we can eliminate the null check in the first method.
Create the new copy right away. That part's easy, right?
If lastC is null, you have an empty list, so you just point both front and back of the list to your new node.
Otherwise you point the old tail's next pointer to your new node and update the tail pointer to remain pointed at the tail.
Either way, you can safely recurse with the next object in the original list.
Advantages of this method, aside from working, is that you don't destroy the original list, and it's pretty clear to read.

Finding K-th to last element of a singly linked list

I am currently reading the book "Crack the Coding Interview" (5th edition). There is a particular problem in it saying Implement an algorithm to find kth to last element of a singly linked list. There are various approaches discussed to the problem. I am particularly confused by the recursive solution. It goes as follows (shamelessly copying it from the book):
public class IntWrapper {
public int value = 0;
}
LinkedListNode nthToLastR2(LinkedListNode head, int k, IntWrapper i){
if(head == null){
return null;
}
LinkedListNode node = nthToLastR2(head.next, k, i);
i.value = i.value + 1;
if(i.value == k) { // We've found the kth element
return head;
}
return node;
}
My question is: We are returning a LinkedListNode when we find that particular node and we are returning a LinkedListNode even when we don't find that particular node. So there is no means to tell kth node from any other node. Can anyone please tell me if my observation is correct or not? If yes, how can we make it correct (other than, of course doing a System.out.println before the return head because that would be just printing the node and not returning it) ?
The trick in this recursive function is that the recursive call happens first - this means that by the time any of the code after the call executes, we'll already be at the last node. Once we get to the end, our function will return null because there is nothing left (head is now null). The final function of our callstack returns null, which means that node = null. Now the function checks to see if the current node is the k-th one (using the accumulator i).
There are two possible cases:
We aren't at the correct node: Our function simply returns node, which as we recall is null. Thus for the next higher function in the callstack, things look just like if it had hit the end, except that i is larger.
We are at the correct node: We return head, not node (remember node = null). In this case, we propagate back up the callstack again, but this time instead of node being null at each layer, it's head, which is the node we want. Eventually we get back to the top, and return the correct element.
So, simply put, the function keeps returning null until we find the element, then it keeps returning the element.
Poorly drawn mspaint picture:
Short answer: Your observation is incorrect, the example works as is. To the expanation first simple recusion example:
Factorials: n! = n*(n-1)*(n-2)...*1
Recursive Function:
int fact(int n) {
if (n==1) {
return 1;
} else {
return n*fact(n-1);
}
}
So basically the function calls itself until it comes to the point where n==1 and then you get a result after the result has come through to the one you called. So basically
fact(3) = 3*fact(2) = 3*2*fact(1) = 3*2*1
The same happens in your example:
It starts by running through the list till the end by calling itself with the next element of the list
LinkedListNode node = nthToLastR2(head.next, k, i);
when it reaches the last node it starts returning stuff
if(head == null){
return null;
}
only then does the last one before that call go to the line
i.value = i.value + 1;
and starts counting from the last node.
Then checks if it has the kth node from the last by checking
if(i.value == k) {
and if it has it return the head it got.
If it hasn't it return the one it got returned from the one before. For example k=4 and seven node
head: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> null
| returning
i= 7 6 5 4 3 2 1 v
3 <- 3 <- 3 <- 3 <-.-null<- null <- null
Each step is an independent evaluation of the same function knowing not who called it and waiting for the one it called to return something.
I'm not sure that the book you are using is that good. They access member variables without getters/setters. You would see that 15 years ago in Java, but it's a big no-no now. They are in their 5th edition (2011), but it seems they were lazy in did not update their examples as the Java conventions were evolving.
Their recursive solution is quite complicated. I wrote a alternate recursive solution below. It keeps a queue of the latest visited nodes. That queue is kept as small as possible. I am using Java 8's Optional where a returned empty value signifies that the list is too short.
Optional<LinkedListNode> recur(
LinkedListNode currentNode,
int nFromLast,
Queue<LinkedListNode> latestNodes) {
if (currentNode == null) { // went past the last node
if (latestNodes.size() > nFromLast)
return Optional.of(latestNodes.remove());
else // the queue is too short
return Optional.empty();
} else {
if (latestNodes.size() == (nFromLast + 1))
latestNodes.remove();
latestNodes.add(currentNode);
return recur(currentNode.getNext(), nFromLast, latestNodes);
}
}
It is called initially with an empty queue:
recur(list, k, new ArrayDeque())
[Warning: this paragraph below is at an advanced level.]
It might seem that my solution wastes memory by keeping the queue, but their solution keeps items in memory on the stack. My solution is tail recursive and theirs is not. Unfortunately, it is not an advantage for the time being since the JVM does not optimize for tail recursion. The JVM also keeps everything (including all copies of the queue) on the stack for my method. At least I think my solution is simpler.

"If" makes NullPointerException

I'm writing program, which do some operations with doublylinked lists(my implementation).
There is one thing which i do not understand and it confusing me a lot.
Ok. So. I have two doubly linked list. I need to create method where argument is a index of first doublylinked list, and on that index i need to put second list.
I wrote that method:
public void PutInPlace(int i){
DoublyLinkedList ldw3 = new DoublyLinkedList(); // New doublylinked list.
Node current = ldw1.tail; // ldw1 - First doublylinked list, created earlier.
Node current1 = ldw2.tail; //ldw2 - Second doublylinked list, created earlier.
int counter = 0;
while(true){
ldw3.AddHead(current.number);
current = current.prev;
counter++;
if(counter == i){ // THAT if makes NullPointerException
ldw3.AddHead(current1.liczba);
current1 = current1.prev;
if(current1 == null)
break;
}
}
I dont wanna put all code, because it is long and can be not-easy to read. So, why "if(counter == i)" makes NullPointerException? Without that "if" program works. Where is the problem?
Thank you for help, guys!
current1 may be null. But you are trying to get the value
if(current1 != null)
{
ldw3.AddHead(current1.liczba);
current1 = current1.prev;
}
instead of
current1 = current1.prev;
(or)
change the statement like this,
if(current1 == null)
break;
ldw3.AddHead(current1.liczba);
current1 = current1.prev;
instead of
ldw3.AddHead(current1.liczba);
current1 = current1.prev;
if(current1 == null)
break;
I think the current variable is the one being null. The i variable has a unique value, let's say 3.
While(true) is an infinite loop, and your condition (counter==i) will be executed only once (since you always increment counter and it will hit the value 3 only once). So unless current1 has no previous, the break will never be it and you will arrive to a point where current has no more previous (making it null and giving an exception when doing current.prev)
A good practice is always checking if an object is null before using one of its methods or attributes.
No, that "if" cannot make a NullPointerException.
First, make sure you recompile everything, and run a test. Then post the output from that test, including the stack trace from the exception.
Second, post the source code verbatim (so the line numbers are clear).
Third, post the javap output for the PutInPlace method.

Trying to implement level order traversal on a binary search tree in Java

Okay, so I'm trying to make a method that will return the level order of a basic binary search tree that carries int values in its nodes. I've figured out most of the other methods, such as insertion, post order and pre order, but I keep running into the same problem with the level order method
Here's the code:
private DoubleStackQueue<Node> queue = new DoubleStackQueue<Node>();
//this is a queue that uses two stacks, one for the front and one for the back.
//it works just like a queue.
public String levelOrder(){
s = ""; //The s is a private String that is implemented earlier
queue.add(this);
while (!queue.isEmpty())
{
Node node = (Node)queue.remove();
if (!(node.equals(null))) {s += ""+node.getVal();}
if (!(left.equals(null))) {queue.add(node.left);}
if (!(right.equals(null))) {queue.add(node.right);}
}
return s;
}
The main problem that I am having is that, when the program gets to a leaf node, it still adds its children to the queue, even though there are no children, just null, so I'll get a queue that has two nulls in front of the actual item in it. I originally had the if statements as (left != null) and such, but that didn't work either. I'm just trying to figure out how to make the program recognize when there aren't any children. What do I need to do?
Several comments:
The primary issue is that you're using left and right instead of node.left and node.right in your comparisons.
To compare against null use if (var != null). Do not use equals(). If a variable is null you cannot call methods on it as that will trigger NullPointerExceptions.
Once you have fixed your code you will never have null inserted into the queue. The first object you add is this which is guaranteed to be non-null, and subsequently you always check for null before inserting items onto the queue. That means your first if (node != null) check is unnecessary.
The cast in (Node) queue.remove() should be unnecessary. Your compiler ought to warn you about this.
Result:
queue.add(this);
while (!queue.isEmpty())
{
Node node = queue.remove();
s += "" + node.getVal();
if (node.left != null) { queue.add(node.left); }
if (node.right != null) { queue.add(node.right); }
}
Within your code I can find the lines
if (!(left.equals(null))) {queue.add(node.left);}
if (!(right.equals(null))) {queue.add(node.right);}
where in the condition it states left and right which are nowhere defined in the parts you show but on the right it reads node.left and node.right. Is this intentionally? I'd expect also node.left and node.right in the if conditions.
Look at this question: Level-order tree traversal
I believe this is the same thing you're trying to achieve, is it not? This is a pretty classic problem, so in my experience it's been discussed over-and-over before.

AVL Tree Balancing

I am working on an assignment that asks me to implement an AVL tree. I'm pretty sure I have the rotation methods correct, but I'm having trouble figuring out when to use them.
For example, the explanation in the book says that I should climb up the same path I went down to insert the node/element. However, I can't have any parent pointers.
Latest code:
public BinaryNode<T> insert(BinaryNode<T> node) {
if (this.getElement().compareTo(node.getElement()) > 0) {
if (this.getLeftChild() != null) {
BinaryNode<T> b = this.getLeftChild().insert(node);
if(!this.isBalanced()) {
this.balance();
}
return b;
} else {
this.setLeftChild(node);
}
} else if (this.getElement().compareTo(node.getElement()) < 0) {
if (this.getRightChild() != null) {
return this.getRightChild().insert(node);
} else {
this.setRightChild(node);
}
}
return this;
}
What I want to do here is climb back up the tree, but it can only check the balancing AFTER it inserts the node. Hence, this being in the else clause.
I also tried putting the balance code where R Samuel Klatchko suggested, but checked the balance on each insert. For example: If one inserts 7, 9, 5, 3, and 1 consecutively, I get a null pointer exception when trying to insert 1.
EDIT: One reason for the above may have something to do with the way I was doing the height. It works fine with a single right rotation if I calculate the height every time with height() but that breaks the O(log(n)) time of an AVL Tree.
Any thoughts on how to accomplish this?
You code is climbing up the same path you went down. Consider this code:
if (this.getLeftChild() != null) {
return this.getLeftChild().insert(node);
}
and modify it slightly:
if (this.getLeftChild() != null) {
boolean b = this.getLeftChild().insert(node);
// do something here
return b;
}
As the code returns from the recursive calls, each return brings you back to the parent. By not immediately returning the value of the recursive call, you have a chance to do your rebalancing.
Update for latest code
Don't forget to rebalance when you've inserted to the right.
You might try passing the parent pointer into the insert method, or you could convert insert into an iterative method and keep an explicit stack on which you record the path down the tree.
By the way, in order to choose which rotation to use, you can just know that a node is unbalanced, you have to know whether the deeper subtree is on the right or on the left. This means that your simple isBalanced method isn't quite enough. It's also inefficient, and will blow the AVL tree's O(log n) complexity, because you compute the heights each time.

Categories