Converting a linkedlist to binary tree - java

I've a linked list that has two links - next and another assume. Initially, all another hold null. Now, I'm trying to convert this to a binary tree with next holding the liftChild and another holding rightChild. However, I want to do this in O(n) and in constant space. I've tried a lot. Below is my code. I'm verifying the result by level-order traversing the resulting tree. Currently, I know what's the mistake but don't know how to solve it. The mistake here is that inside the while loop, I'm changing the links of the node properly, but this means I cannot do node = node.next at the end because node's next is already pointing somewhere ahead in the list. So, I don't know how to traverse every node. Any hint, help is appreciated. Not hw, not interview question or anything. Just trying to learn data structures. So, this tree and ll stuff!
public class LlToBt {
public SpecialNode llToBt(SpecialNode node) {
SpecialNode temp = node;
SpecialNode returnNode = node;
if(node == null)
return null;
if(node.next == null)
return node;
node = returnNode;
while(node != null) {
SpecialNode currentNode = node;
temp = temp.next;
if(temp == null) {
//node.next = null;
//node.another = null;
return returnNode;
}
node.next = temp;
temp = temp.next;
if(temp == null) {
//node.next = null;
//node.another = null;
return returnNode;
}
node.another = temp;
node = currentNode.next;
}
return returnNode;
}
}

If you are changing the link that you will want to traverse before you traverse it, then you need to store off in a different variable the result of the traversal before you change the link. Then after the change, you can traverse using your temporary copy.

Related

Implementing my own LinkedList, insertion of a new element to the Tail doesn't work correctly

I`m trying to implement my own linkedlist and I tackled with this question.
This is add method implementation for linkedlist, supposed to add specified elements to the end of the list.
Below you see a code I found and that works, and you see my code which only shows last 2 elements added no matter how many you add to the list.
The only difference 2 codes have is that he stores rootNode (head) inside currentNode and does his traversing using currentNode. I directly used rootNode to do the same. Can someone explain my what is wrong with my code ?
This is his code that works:
public void add (E val) {
Node newNode = new Node(val, null);
Node currentNode = rootNode;
if (rootNode == null) {
rootNode = newNode;
} else {
while (currentNode.nextNode != null) {
currentNode = currentNode.nextNode;
}
currentNode.setNextNode(newNode);
}
}
And this is my code that only shows last 2 elements added :
public void add (E val) {
Node newNode = new Node(val, null);
if (rootNode == null) {
rootNode = newNode;
} else {
while (rootNode.nextNode != null) {
rootNode = rootNode.nextNode;
}
rootNode.setNextNode(newNode);
}
}
That happens because you're resigning the rootNode while iterating.
By making this, you are erasing all previous state of the list, which you can access only via root. That's way the only node that remain in the list are root and its next node.
In order to iterate over the list, you should introduce the local variable like in the first version. There's no other way around.
And I suggest to simplify the method a bit by returning after checking whether the root is null, there will be no in nesting the loop into the additional block of curly braces:
public void add (E val) {
Node newNode = new Node(val,null);
if(rootNode == null) {
rootNode = newNode;
return;
}
Node currentNode = rootNode;
while (rootNode.nextNode != null) {
rootNode = rootNode.nextNode;
}
rootNode.setNextNode(newNode);
}
Because you are changing root node, after add method ends, you have only the root node and the next node of it, do not change root node if it is not null.
For instance, you call add Method for nodes A, B, and C.
For the first time root is A, then when you call add(B), as the root node is not null already, loop will not work in the else statement and the next of A will be B, then when you call add(C), while loop will work one iteration and B will become root node(you lost A) and the next of B will be C node.

Algorithm: Merge Sort with linked list missing items

I am trying to sort my linked list with merge sort. The list is actually sorted but it is kind of missing first item(s).
Merge sort functions:
public Node mergeSort(Node head) {
if (head == null || head.next == null) {
return head;
}
Node middle = middleElement(head);
Node nextofMiddle = middle.next;
middle.next = null;
return merge(mergeSort(head), mergeSort(nextofMiddle));
}
public Node merge(Node left, Node right) {
Node temp = new Node();
Node newHead = temp;
while (left != null && right != null) {
if (left.info <= right.info) {
temp.next = left;
temp = left;
left = temp.next;
} else {
temp.next = right;
temp = right;
right = temp.next;
}
}
temp.next = (left == null) ? right : left;
return newHead;
}
public Node middleElement(Node head) {
if (head == null) {
return head;
}
Node slow = head;
Node fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
So I printed the list to the screen using traverse:
public static void main(String[] args) {
MyLinkedList mll = new MyLinkedList();
mll.insert(3);
mll.insert(5);
mll.insert(9);
mll.insert(1);
mll.insert(8);
mll.insert(7);
mll.insert(2);
mll.mergeSort(mll.head);
mll.traverse();
}
I have result like this:
1 and 2 missing!
After checking, i noticed that the "tail" of the linked list value is still 2. I don't know why can someone help?. I'm really new to programming so sorry for any inconvenience. Thank you for reading!
You're not far from a correct solution. I was able to get a working sort by adding 1 line and changing 3.
Your merge isn't doing what you think it is.
Allocating a false head node (what you call temp, not a good choice of name; try falseHead) is a fine idea. Then falseHead.next is the true head. That's what you'll finally return as the sorted list. Note that initially it's null, which is what you'd expect.
What you're missing is a variable tail to reference the current last node in the merged list. Since there is initially no last node at all, this should be initialized equal to falseHead. Consequently, when you append the first element to the tail of the current result by setting tail.next, you'll also be setting falseHead.next, i.e. creating the head element. It all works out.
Now, what is the logic for, say, removing the current head of the right list and appending it to the merge result? It's just 3 steps:
Do the append operation by making tail.next the current head of right.
Update tail to tail.next.
Remove the head of right by updating right to right.next.
Of course the left side is similar.
Good luck. You're close.
You have a couple problems that I can see. One, mentioned by #rcgldr, in the comments is that you merge method is returning the temp node newHead, but that node was no value and is not part of your graph. You need to return it's child newHead.next.
The other problem is that you never reset the head of your list. So after all the sorting, the head of mll still points to the original head, which in this case is 3. So when you traverse the list you skip 1 and 2. I'm not sure what your linked list class looks like but something like this should be close -- just assign the final node returned by mergeSort to the head of the list. Then when you traverse you should be starting in the right spot:
mll.head = mll.mergeSort(mll.head);
mll.traverse();

Why can't I just do node = node.next to iterate through linked list?

I am currently doing a Cracking the Coding Interview Problem (2.4) and I am supposed to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. However, I am really confused as to why a temporary variable "next" is needed and why is node.next nulled below it. Why can't I just do node = node.next at the end of the while loop?
I am simply creating two linked lists, before and after, and merging them together once the correct values are put into each list.
public static Node partition(Node node, int x) {
Node beforeStart = null;
Node beforeEnd = null;
Node afterStart = null;
Node afterEnd = null;
/* Partition list */
while (node != null) {
Node next = node.next;
node.next = null;
if (node.data < x) {
if (beforeStart == null) {
beforeStart = node;
beforeEnd = beforeStart;
} else {
beforeEnd.next = node;
beforeEnd = beforeEnd.next;
}
} else {
if (afterStart == null) {
afterStart = node;
afterEnd = afterStart;
} else {
afterEnd.next = node;
afterEnd = afterEnd.next;
}
}
node = next;
}
/* Merge before list and after list */
if (beforeStart == null) {
return afterStart;
}
beforeEnd.next = afterStart;
return beforeStart;
}
Why can't I just do node = node.next at the end of the while loop?
It can be done this way. After doing the partition, for each list, you need to set the last node's next pointer to NULL. This will just take two lines of code.
The example code is using next = node.next and node.next = NULL to terminate each list during the partition process, but in this case that's not needed, since the lists don't need NULL terminators until after the partition process is done.
The loop in your question removes nodes from the head of the original list, and appends them to the before list or the after list, until the original list is empty. Then it concatenates the before and after lists.
That's easy to explain and easy to understand.
It can be done without the temporary next or nulling out node.next in every iteration, but then the above description would no longer apply -- nodes would not be removed from the original list in every iteration, the before list and after list would not contain only the appropriate nodes, the operation you perform on them is not 'appending', and nodes would even appear in multiple lists for a while.
Your algorithm would suddenly be a lot more difficult to describe and understand. That is a bad thing in software development, and a bad thing in a coding interview.

Reversing a linked-list

I am writing a simple recursive code to reverse a linked-list in Java. Strangely it returns the same node.
Node reverse(Node ptr) {
if (ptr.link == null)
return ptr;
Node second = ptr.link;
ptr.link = null;
Node rest = reverse(second);
rest.link = ptr;
return rest;
}
Why isn't this working?
Your current approach won't work, the rest value that's being returned from the recursive call doesn't point to the last element in the list (which should be the insertion point for the nodes), instead it's pointing to the first element of the result. In other words, this line isn't correctly building the output:
rest.link = ptr;
For successfully reversing a list, one strategy is to use an accumulator parameter, so we can insert at the head of the list as the recursion unwinds - bear in mind that the recursion starts to "go back" in reverse order with respect to the elements in the list. Try this, it's a tail-recursive solution:
Node reverse(Node ptr, Node acc) {
if (ptr == null)
return acc;
Node second = ptr.link;
ptr.link = acc;
return reverse(second, ptr);
}
Call the above method like this:
Node reversedList = reverse(list, null);
Be aware that the input list will be modified in-place and won't be the same after the method returns, any variable that holds a reference to list will be affected. If that's a problem, you should create a copy of list before passing it to reverse().
Oscar is correct that the return value from recursive call does not point to the last element.
There is another algorithm that does not use accumulator parameter:
function reverse(node) {
if (node.next == null)
return node;
var tail = reverse(node.next);
node.next.next = node;
node.next = null;
return tail;
}
Node reverseNode(Node node){
Node head = null;
While(node.next != null){
Node n = new Node(node.data);
n.next = head;
head = n;
node = node.next;
}
return head;}
You know you don't have to write a recursive function

How to reverse LinkedList in java

Please accept my apologies first, but I could not reverse my Linked List in java..
I have class and inner class:
MyList{
class Element{
private Element next;
public Element getNext(){return next;}
}
public void reverseMyList(Element curr) {
if (curr.next == null) {
head = curr.next;
return;
}
reverseMyList(curr.next);
while (curr.next != null) {
curr.next.next = curr.next;
curr.next = null;
}
}//:~
I need to reverse my List, I am using method reverseMyList, which needs Element curr.
If my way of thinking in this case is correct ?
Thank you in advance!
Since this kinda looks like homework, I'm not going to lay out the entire solution here, but I will explain how you should conceptually do it.
Imagine that you have 2 linked lists. You have your input list that you need to reverse, and you have an empty one.
If you keep taking the first element off of the original list, and keep putting that on the front of the new list until your original list is empty, than your new list will be what the original was, except reversed.
public static void Reverse(Element element)
{
Element current = element;
Element next = current.Next;
Element nextToNext;
var first = current;
while (next != null && next.Next != null)
{
nextToNext = next.Next;
next.Next = current;
current = next;
next = nextToNext;
}
if (next != null)
{
next.Next = current;
}
first.Next = null;
}
the method you are looking for already exist in package java.utils:
Collections.reverse(mylist);
this method will change the order of element direcly inside your list and you dont need to instance a new list-object... here you can find more specified documentation

Categories