Recursive Linked List. What am I doing wrong? - java

public class Reverse {
public static void printLL(Node head) {
while(head!=null){
System.out.print(head.getData()+"-->");
head=head.next;
}
}
public static Node reverseLL(Node head){
if(head == null) {
return head;
}
return reverseLL(head.next);
}
public static void main(String[] args) {
Node first=new Node(10);
Node head=first;
Node second=new Node(20);
first.next=second;
Node third=new Node(30);
second.next=third;
Node fourth=new Node(40);
third.next=fourth;
printLL(head);
System.out.println("\nReverse of Linked List is \n");
head=reverseLL(head);
printLL(head);
}
}
Here is my code. It is not printing anything.
I think that due to recursion, it is pointing to the null pointer and hence no data is present at null position.
Please tell me what can I do to make the code correct.
Thanks in advance

Your reverseLL simply goes through all the Nodes and when it reaches the last one doing if(head==null), null is returned.
You need to fix the reverseLL function. Try adding traces into the function to understand what it does step by step.

You seemn to have missed a crucial point about recursion - you have to call yourself.
I will suggest a change to printLL that should demonstrate one possible recursive solution that should work.
public static void printLL(Node head) {
if (head != null) {
System.out.print(head.getData() + "-->");
printLL(head.next);
}
}
Note how the code basically says if there is a head, print it's data and then print it's head.next.

The problem is that your reverseLL does not do anything to the head after calling itself recursively.
The base case is right: when head is null, you return null. The recursive step, however, is not complete: you need to reverse the rest of the list, but then you have to attach it back to the head.
The simplest way to accomplish this is to pass an extra parameter for the prior node, so that you could do
head.next = prior;
inside your recursive method. Here is how your "wrapper" method would look:
public static Node reverseLL(Node head) {
if(head==null){
return null;
}
return reverseLL(head, null);
}
Note that it is not recursive - all it does is calling a two-argument overload.
The recursive method knows that head is never null, so its base case is head.next == null:
public static Node reverseLL(Node head, Node prior) {
Node res;
if (head.next == null) {
res = head;
} else {
res = reverseLL(head.next, head);
}
head.next = prior;
return res;
}
The reversal of the head node is done in the assignment prior to the return. Note how the method returns the last non-null node in the chain.
Demo

Related

Head is getting reversed in a linked list for a palindrome validation algo

I am trying to write an algorithm that checks if an input LinkedList is a palindrome or not. My algorithm is as follows:
Set a dummy node to point to the head of the input linkedList
Use a handler to store the reversed linkedlist
Run a loop to compare the values from front and back
My error: I know that the algorithm is wrong, because the output that I get seems to say that my original head is pointing in the wrong direction. I cannot figure out why, since I have used handler nodes while reversing as well.
The code is as follows:
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null) return true;
ListNode dummy = head;
ListNode MatchList = null;
MatchList=reverseList(head);
while(dummy!=null)
{
if(dummy.val!=MatchList.val)
{return false;}
MatchList=MatchList.next;
dummy=dummy.next;
}
return true;
}
public ListNode reverseList(ListNode head) {
ListNode dummy, newHead;
newHead=head;
ListNode another=newHead;
ListNode prev=null;
while(another!=null)
{
dummy=another.next;
another.next=prev;
prev=another;
another=dummy;
}
return prev;
}
}
The problem in your attempt is that when you reverse the list, it happens to that list. Yet your code deals with it as if it is a second list, independent from the first list. But because it is not, the head node has become the tail, and so after reverseList has been called, head.next (i.e. dummy.next) is going to be null.
A simple idea would be to change reverseList so that it creates a new list, calling the ListNode constructor for each node it encounters, but then linking them in the opposite direction.
This is however not an ideal solution, as it needs O(n) auxiliary space.
There is the following "trick" you can apply:
Find the middle node of the list (or if the size is even, the first one of the second half).
Reverse the list that starts at that node, i.e. reverse the second half of the list
Now you can walk in both halves and compare the values in tandem.
To make that work, here is a function you could use:
public ListNode middleNode(ListNode head) {
ListNode fast = head;
while (fast != null && fast.next != null) {
head = head.next;
fast = fast.next.next;
}
return head;
}
And now you can do:
public boolean isPalindrome(ListNode head) {
if (head == null) return true;
ListNode mid = middleNode(head);
ListNode tail = reverseList(mid);
while (tail != null) {
if (head.val != tail.val) return false;
tail = tail.next;
head = head.next;
}
return true;
}

Update value of a reference in recursive method - best practices

I am trying to see how I can update a reference variable in Java methods in a better way. I know that Java references are pass by value - in other words, if I change the value of the reference in a method, it wont retain it in the caller method. But at the same time, I am trying to see how I can deal with these situations better. In most cases we need to return value from a method in recursion, say its base case, just like below where I resort to maintaining a static variable to hold the new head of a linked list that is being reversed. What are the more sensible options that I can use here?.
public static LinkedList _head = null;
public static LinkedList reverseLinkedList(LinkedList head)
{
reverseLinkedListInternal( head );
return _head;
}
public static LinkedList reverseLinkedListInternal( LinkedList node )
{
if( node.next == null )
{
_head = node;
return node;
}
LinkedList tmp = reverseLinkedListInternal( node.next );
tmp.next = node;
node.next = null;
return node;
}
You just don't need the static variable here. You should be just using the return value, whereas at the moment it's simply being ignored.
This is the kind of solution I would write. Obviously this might not fall into the constraints of your exercise as it is written as if it were a method of a LinkedList, which would make a lot more sense in the real world. However the concept is the same, so hopefully it will help you to spot your mistakes.
public void reverse() {
reverseInternal(head);
}
public Node reverseInternal(Node node) {
if (node.next == null) {
return node;
}
Node reversedTail = reverseInternal(node.next);
reversedTail.next = node;
node.next = null;
return reversedTail;
}

Recursion of Linked List

When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}

Reversing a singly linked, sentinel based, list recursively (works, but not in the way I'd like it to)

I'm preparing for interviews and wrote up this simple function for recursively reversing a singly linked list. The first node is a sentinel node, head. The following code works fine for: list.reverse(list.head.next), but I can't seem to get it to work if I just pass it head.
public Node<T> reverse(Node<T> current)
{
if (current == null)
return head;
if (current.next == null)
{
head.next = current;
return current;
}
reverse(current.next).next = current;
current.next = null;
return current;
}
I assume it doesn't work when I pass it head instead of head.next because I say current.next = null, but even if I check if current == head or if current.data == null and only use current.next = null when those aren't true, it still doesn't work. I'm sure there's a really simple fix, but I'm just not seeing it right now.
The above if passed head returns an empty list, and if the suggested changes are made, simply doesn't finish running, but I don't get any sort of error.
(EDITED)
I kind of get your problem now:
Simply speaking, the sentinel head acts simply as a pointer to the first node, instead of being part of the linked list. Therefore it will not be involved in the reverse process, and need to handle separately.
which means, the original list looks like:
HEAD -> a -> b -> c -> null
after reverse, it should look like
HEAD -> c -> b -> a -> null
In brief, it should look like (assume your code already works when passing in head.next)
public Node<T> reverse(Node<T> current)
{
if (current == head) {
return reverse(current.next);
}
// rest of your original code.
}
Just a further suggestion:
Your reverse() method, as an public instance method of your list class, shouldn't accept the current node, as it is conceptually meaningless for caller.
I believe you should make this method protected, which means something like:
public void reverse() {
this.head = reverseInternal(head);
}
private Node<T> reverseInternal(Node<T> node) {
// your original reverse logic
}
With such encapsulation, you don't even need to struggle before how to make your reverse works when you pass in the sentinel head: you can simply call reverseInternal(head.next) in your public reverse() method.
First: if it returns an empty list it doesn't "work".
There is no need for head to be an empty node. You should normally just keep the first node (in your case list.head.next) as your list.head. head should be a reference to where the list starts, not a separate node.
The reason your code empties the list when you pass it list.head is it sets list.head.next to null. This is because you assume the node you pass to the list is a regular one, while your head node is special.
Here's a solution for your assumptions (I'll assume someone insisted on this bizarre detached head thing. Just don't do it if you're designing the list yourself. Please...)
public Node<T> reverse(Node<T> current)
{
if (current == null)
return head;
if (current.next == null)
{
head.next = current;
return current;
}
Node<T> temp = current.next;
current.next = null;
head.next = temp;
reverse(temp).next = current;
return current;
}
Explanation: This still sets the last node's next to null, but it pushes the list's head one spot down as it runs through the list, eventually pointing it to the last (now first) member.
This reeks of homework.
But still.
In general:
f(Node<T> current, ...) {
f(current.next, ...);
}
For a list a > b > c > d > e sitting in the midle at d, one
probably has built c > b > a already, so guess what is needed as additional parameter to f?
Good luck.
After comments:
public Node<T> reverse(Node<T> current)
{
return reverseRec(current, null);
}
/**
* #param current to-do (sub-)list.
* #param resultDone done reversed list sofar.
* #return reversed result.
*/
public Node<T> reverseRecursively(Node<T> current, Node<T> resultDone)
{
if (current == null) {
return resultDone;
}
Node<T> next = current.next;
current.next = resultDone;
return reverseRecursively(next, current);
}

LinkedList remove method

What is a doubly linked list's remove method?
The same algorithm that Bill the Lizard said, but in a graphical way :-)
(source: jaffasoft.co.uk)
The general algorithm is as follows:
Find the node to remove.
node.previous.next = node.next
node.next.previous = node.previous
node.previous = null
node.next = null
Dispose of node if you're in a non-GC environment
You have to check the previous and next nodes for null to see if you're removing the head or the tail, but those are the easy cases.
public void remove ()
{
if (getPreviousNode () != null)
getPreviousNode ().setNextNode (getNextNode ());
if (getNextNode () != null)
getNextNode ().setPreviousNode (getPreviousNode ());
}
Doubly Linked List Implementation Remove Methods (from my second programming assignment):
public void remove(int index) {
if(index<0 || index>size())
throw new IndexOutOfBoundsException("Index out of bounds. Can't remove a node. No node exists at the specified index");
if(size()==0) {
throw new NullPointerException("Empty list");
}
if(!isEmpty()) {
Node current;
//starting next one to our head
current = head.next;
for(int i=0;i<index;i++) {
current = current.next;
}
current.previous.next = current.next;
current.next.previous = current.previous;
numOfNodes--;
sizeChangeCount++;
}
}
public boolean remove(T o) {
Node current = head;
for(int i=0;i<size();i++) {
current=current.next;
if(current.data.equals(o)) {
current.previous.next = current.next;
current.next.previous = current.previous;
numOfNodes--;
sizeChangeCount++;
return true;
}
}
return false;
}
Are you asking for the name of a method in the api? That answer would simply be remove, assuming you are asking about java.util.LinkedList which is in fact a double linked list.
...or are you asking about what the name of the algorithm to remove an element from that type of data structure is called? Well.. the answer for that would also be to remove an element. Now for the actual algorithm to do it... it's really just a matter of changing the next pointer in the previous node and the last pointer in the next node. However, if you are using your data structure from multiple threads, you will need to either synchronize the remove method, or do the removal steps in an order that will make sense for your usage pattern for the data structure.
What about the current pointer pointer? You have to move crnt to the next node.
http://pastebin.ca/1249635

Categories