Java Reverse a linked list pairwise - java

I am trying to reverse a linked list pairwise i.e as follows
1->2->3->4->5 changed to 2->1->4->3->5
I have been able to do that recursively. However, I am getting confused while doing it iteratively.
public class FastList<Item>
{
private Node<Item> first;
private static class Node<Item>
{
Item item;
Node<Item> next;
}
public void swapPairwiseIterative() // not working
{
if(first == null || first.next==null)
return;
Node one = first, two;
first= first.next;
while ( one != null || one.next != null )
{
two = one.next;
one.next = two.next;
two.next = one;
one = one.next.next;
}
}
}
On debugging, I noticed that I am able to swap the two nodes correctly, but am not able to assign it back to the first instance variable, which points to the first element of the list. How do I do that ?
Also, the line
first= first.next;
looks a bit hacky. Please suggest a more natural way of doing it.

Try something like this:
public void swapPairwiseIteratively() {
if(first == null || first.next==null) return;
Node one = first, two = first.next, prev = null;
first = two;
while (one != null && two != null) {
// the previous node should point to two
if (prev != null) prev.next = two;
// node one should point to the one after two
one.next = two.next;
// node two should point to one
two.next = one;
// getting ready for next iteration
// one (now the last node) is the prev node
prev = one;
// one is prev's successor
one = prev.next;
// two is prev's successor's successor
if (prev.next != null) two = prev.next.next;
else two = null;
}
}
I am not sure you can do it with only two pointers instead of three. I would work from the solution above (I haven't tested it but it should be correct) and figure out if it can be improved. I don't think the line first = two can be removed.
You could remove the condition if (prev != null) if you move the first pair swapping out of the loop (an optimization that is premature in this example).

You can do it either recursively or non-recursively.
public void reverseRecursive(Node startNode)
{
Item tmp;
if(startNode==null || startNode.next ==null)
return;
else
{
tmp = startNode.item;
startNode.item = startNode.next.item;
startNode.next.item = tmp;
reverseRecursive(startNode.next.next);
}
}
Non Recursively
public void reverseNonRecursive()
{
Node startNode = head;
Item temp;
while(startNode != null && startNode.next != null)
{
temp = startNode.item;
startNode.item = startNode.next.item;
startNode.next.item= temp;
startNode = startNode.next.next;
}
}

Related

Remove Duplicates from Linked List

So I have a linked list that I am trying to remove duplicates from.
My basic algorithm that I thought up is to pretty much use the runner technique. Where I keep two pointers to compare adjacent elements. If they are the same I change the pointer of p1 to point to p1.next.next if not I keep traversing the list. However I keep getting a null pointer exception in the solution I have typed.
Node RemoveDuplicates(Node head) {
// This is a "method-only" submission.
// You only need to complete this method.
if (head == null){
return null;
}
Node current = head;
Node runner = head;
while(current != null && runner != null && runner.next != null){
runner = runner.next;
if(runner.data == current.data){
if(current.next != null){
current = current.next.next;
}
}else{
current = current.next;
}
}
return current;
}
At the point that I exit the while loop current is null. Which I think is the problem. How would I return the head of the altered list.
OK, although you've already accepted an answer, here's some example code using recursion to remove the dups from an ordered list per your request in the comments. (if your list isn't ordered, order it :) )
public Node removeDups(Node root) {
if (root.next == null)
return root;
root.next = removeDups(root.next);
if (root.data == root.next.data)
return root.next;
return root;
} // call as root = removeDups(root);
As you mentioned, recursion isn't really necessary here but you're using a Node-based linked list which is recursively defined. So, when it makes sense, the elegance of the solution has its benefits.
What I like about it is that you're not doing any node.next.next or needing to check for that null case. Once the stack starts unwinding, you're already in a position to start checking for dups. Then it's just a matter of comparing root.data and root.next.data; both of which you already know exist.
You can do this with single traversal with 2 pointer.and also this code works with single while loop.
public Node deleteDuplicates(Node head) {
Node current=head;
if (head == null)
return null;
else
{
Node runner=head.next;
while(head.next!=null && runner!=null)
{
if(head.val == runner.val)
prev=runner.next;
else
{
head.next=runner;
head=head.next;
prev=runner.next;
}
}
head.next=runner;
}
return current;
}
First of all, you'll want to return head at the end, so that you are returning the list, not just the last element.
Second thing, you'll want to modify the .next references instead of assigning them in some of the cases.
Note this doesn't work if the list isn't sorted.
Before: 1 1 3 3
After: 1 3
This code works (and I've tested it)
static Node RemoveDuplicates(Node head) {
if (head == null) return null;
Node current = head;
Node runner = head;
while (current != null && current.next != null) {
runner = current.next;
while (runner != null && runner.data == current.data) {
current.next = runner.next; // skip the repeat
runner = runner.next;
}
current = current.next;
}
return head;
}
You can do this in a single traversal. Just maintain two pointers temp
and next_of_next. Make temp iterate for each node and when the data of temp and the next node is equal, point next_of_next to the alternate node after temp and delete the node after temp.
Node removeDuplicates(Node head)
{
Node temp = head;
Node next_of_next;
if (head == null)
return;
while (temp.next != null)
{
if (temp.data == temp.next.data)
{
next_of_next = temp.next.next;
temp.next = null;
temp.next = next_of_next;
}
else
temp = temp.next;
}
return head ;
}
Here an apporach without recursion using a HashSet:
public void RemoveDuplicates()
{
if (head != null)
{
var hm = new HashSet<T>();
Node current = head;
Node prev = null;
while (current != null)
{
if (!hm.Contains(current.Value))
{
hm.Add(current.Value);
prev = current;
current = current.Next;
}
else
{
prev.Next = current.Next;
current = prev.Next;
}
}
}
return head;
}

Segregate even and odd nodes in a Linked List

Given, a linked-list, I'm trying to partition it into so that the even nodes come before the odd nodes. My approach is to create two different linked-list (even and odd) to store even numbers and odd numbers. However, I'm running into a problem when I want to add to the even or odd linked list (I commented the part that I think is giving me problem in my code below). Thanks!
public class SeperateOddEven {
static Node head;
static int count;
public static class Node {
int data;
Node next;
private Node(int data) {
this.data = data;
next = null;
count++;
}
}
public void seperate() {
Node even = null;
Node odd = null;
Node temp;
// go through each linked-list and place node in new list depending on whether they are even or odd
while(head != null) {
// if even, place in even linked-list
if(head.data % 2 == 0) {
temp = new Node(head.data);
even = temp; // Problem here
even = even.next; // and here
} else { // if head.data % 2 != 0
temp = new Node(head.data);
odd = temp;
odd = odd.next;
}
head = head.next;
}
toString(even);
//toString(odd);
}
public void toString(Node node) {
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
public static void main(String[] args) {
SeperateOddEven s = new SeperateOddEven();
head = new Node(8);
head.next = new Node(12);
head.next.next = new Node(10);
head.next.next.next = new Node(5);
head.next.next.next.next = new Node(4);
head.next.next.next.next.next = new Node(1);
head.next.next.next.next.next.next = new Node(6);
System.out.println("original list: ");
s.toString(head);
s.seperate();
}
}
I believe you identified exactly where the problem is. Let's go line by line:
temp = new Node(head.data);
The extra temp variable is unnecessary but fine.
even = temp;
A problem arises on the next line however. You assign even to temp (making temp unnecessary). If something was previously stored in even, it is now lost to the garbage collector because you now have no reference to it. even and temp are now both references to the same Node object.
What I think you might have wanted to do was to say even.next = temp. This would start to create a list, but with only a single reference you would have to use that reference to point to the head of the list. Each time you wanted to append to the list, you would need to loop through it until you found the end. If you instead tried to make this single reference point to the tail of the list, you would no longer have any way to get back to the head because your Nodes only have next references, and not prev references (a list with bidirectional references is called a doubly linked list).
even = even.next;
Because even (and temp) both point to the newly created Node object, the even.next property is null. So when this line executes, even now points to null. The work inside the loop has accomplished nothing because you immediately lose references to every Node you create.
Try something like this:
// Must keep track of head reference, because your Nodes can only go forward
Node evenHead = null;
Node evenTail = null;
Node oddHead = null;
Node oddTail = null;
while (head != null) {
if(head.data % 2 == 0) {
if (evenHead == null) {
// The even list is empty, set the head and tail
evenHead = new Node(head.data);
evenTail = evenHead;
} else {
// Append to the end of the even list
evenTail.next = new Node(head.data);
evenTail = evenTail.next;
}
} else {
// similar code for odd, consider creating a method to avoid repetition
}
}
You can also try this :
while (head != null) {
// if even, place in even linked-list
temp = new Node(head.data);
if (head.data % 2 == 0) {
if(even == null) {
even = temp;
} else{
Node insertionNode = even;
while(insertionNode.next != null)
insertionNode = insertionNode.next;
insertionNode.next = temp;
}
} else { // if head.data % 2 != 0
if(odd == null) {
odd = temp;
} else{
Node insertionNode = odd;
while(insertionNode.next != null)
insertionNode = insertionNode.next;
insertionNode.next = temp;
}
}
head = head.next;
}

Why doesn't this merge-sort function cause an infinite loop?

I'm working on a project that requires me to implement merge-sort on a linked list and I am using the code from this post Here to help me. Can someone explain to why on line 6, when I call return merge(merge_sort(head),merge_sort(sHalf)); the method merge_sort(head) inside of it, which contains the same head pointer doesn't cause an infinite loop? It seems to me that it is starting all over again with the same head pointer.
public Node merge_sort(Node head) {
if(head == null || head.next == null) { return head; }
Node middle = getMiddle(head); //get the middle of the list
Node sHalf = middle.next; middle.next = null; //split the list into two halfs
return merge(merge_sort(head),merge_sort(sHalf)); //recurse on that
}
//Merge subroutine to merge two sorted lists
public Node merge(Node a, Node b) {
Node dummyHead, curr; dummyHead = new Node(); curr = dummyHead;
while(a !=null && b!= null) {
if(a.info <= b.info) { curr.next = a; a = a.next; }
else { curr.next = b; b = b.next; }
curr = curr.next;
}
curr.next = (a == null) ? b : a;
return dummyHead.next;
}
//Finding the middle element of the list for splitting
public Node getMiddle(Node head) {
if(head == null) { return head; }
Node slow, fast; slow = fast = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next; fast = fast.next.next;
}
return slow;
}
It's because of the previous line:
Node sHalf = middle.next; middle.next = null;
Specifically, the middle.next = null; part.
Understand that even though the head pointer is the same, we are splitting the list into half, using middle.next = null. So, in the next recursive call, it's only half the linked list which was sent originally.
And at one point, it will reach head.next == null condition.

How do I traverse a link list looking two nodes ahead?

I have a link list, and I want to be able to look two nodes ahead. I need to check if the first two nodes have integers, and if they do, and the third node says ADD, then I need to condense that information into one node and free the other two nodes.
I'm confused about what should go in my while loop. I check if the third node points to null, but somehow that's not giving me the right output. I don't know if I'm handling my node.next correctly either. Some of this is pseudocode now.
while(node1.next.next.next != NULL){
if((node1.data.isInteger() && (node2.data.isInteger()){
if(node3.data.equals('add')){
node1.data = node1.data + node2.data;
} else {
//ERROR
}
garbage_ptr1 = node2;
garbage_ptr2 = node3;
node1.next = node3.next;
free(garbage_ptr1);
free(garbage_ptr2);
node2.next = node1.next.next;
node3.next = node2.next.next;
} else {
node1.next = node1.next.next;
node2.next = node1.next.next;
node3.next = node2.next.next;
}
An approach that I find easier is to maintain a small array that acts as a window onto the list, and to look for matches on the array. The code also becomes a lot cleaner and simpler if you move your null checks into utility methods. By doing these things, the loop over the list only needs to check the last element of the window to terminate.
A sketch of this in Java:
/* small utility methods to avoid null checks everywhere */
public static Node getNext(Node n) { return n != null ? n.next : null; }
public static boolean isInteger(Node n) {
return (n != null) && (n.data != null) && (n.data instanceof Integer);
}
public static boolean isAdd(Node n) {
return (n != null) && (n.data != null) && n.data.equals("add");
}
/* checks for a match in the 3-node window */
public boolean isMatch(Node[] w) {
return isInteger(w[0]) && isInteger(w[1]) && isAdd(w[2]);
}
/* Loads the 3-node window with 'n' and the next two nodes on the list */
public void loadWindow(Node[] w, Node n) {
w[0] = n; w[1] = getNext(w[0]); w[2] = getNext(w[1]);
}
/* shifts the window down by one node */
public void shiftWindow(Node[] w) { loadWindow(w, w[1]); }
...
Node[] window = new Node[3];
loadWindow( window, node1 );
while (window[2] != null) {
if (isMatch(window)) {
window[0].data = stack[0].data + stack[1].data;
window[0].next = window[2].next;
loadWindow(window, window[0]); // reload the stack after eliminating two nodes
} else {
shiftWindow( window );
}
}

Converting an ordered binary tree to a doubly circular link list

I have a ordered binary tree:
4
|
|-------|
2 5
|
|-------|
1 3
The leaves point to null. I have to create a doubly link list which should look like
1<->2<->3<->4<->5
(Obviously 5 should point to 1)
The node class is as follows:
class Node {
Node left;
Node right;
int value;
public Node(int value)
{
this.value = value;
left = null;
right = null;
}
}
As you can see the doubly link list is ordered (sorted) as well.
Question: I have to create the linked list form the tree without using any extra pointers. The left pointer of the tree should be the previous pointer of the list and the right pointer of the tree should be the next pointer of the list.
What I thought off: Since the tree is an ordered tree, the inorder traversal would give me a sorted list. But while doing the inorder traversal I am not able to see, where and how to move the pointers to form a doubly linked list.
P.S I checked some variations of this question but none of them gave me any clues.
It sounds like you need a method that accepts a Node reference to the root of the tree and returns a Node reference to the head of a circular list, where no new Node objects are created. I would approach this recursively, starting with the simple tree:
2
|
|-----|
1 3
You don't say whether the tree is guaranteed to be full, so we need to allow for 1 and/or 3 being null. The following method should work for this simple tree:
Node simpleTreeToList(Node root) {
if (root == null) {
return null;
}
Node left = root.left;
Node right = root.right;
Node head;
if (left == null) {
head = root;
} else {
head = left;
left.right = root;
// root.left is already correct
}
if (right == null) {
head.left = root;
root.right = head;
} else {
head.left = right;
right.right = head;
right.left = root;
}
return head;
}
Once it is clear how this works, it isn't too hard to generalize it to a recursive method that works for any tree. It is a very similar method:
Node treeToList(Node root) {
if (root == null) {
return null;
}
Node leftTree = treeToList(root.left);
Node rightTree = treeToList(root.right);
Node head;
if (leftTree == null) {
head = root;
} else {
head = leftTree;
leftTree.left.right = root;
root.left = leftTree.left;
}
if (rightTree == null) {
head.left = root;
root.right = head;
} else {
head.left = rightTree.left;
rightTree.left.right = head;
rightTree.left = root;
root.right = rightTree;
}
return head;
}
If I got all the link assignments covered correctly, this should be all you need.
Do an in-order traversal of the list, adding each list item to the doubly linked list as you encounter it. When done, add an explicit link between the first and last items.
Update 3/6/2012: Since you must reuse the Node objects you already have, after you put the node objects into the the list, you can then iterate over the list and reset the left and right pointers of the Node objects to point to their siblings. Once that is done, you can get rid of the list and simply return the first node object.
This should also work:
NodeLL first = null;
NodeLL last = null;
private void convertToLL(NodeBST root) {
if (root == null) {
return;
}
NodeLL newNode = new NodeLL(root.data);
convertToLL(root.left);
final NodeLL l = last;
last = newNode;
if (l == null)
first = newNode;
else {
l.next = newNode;
last.prev = l;
}
convertToLL(root.right);
}
Let your recursion return the left and right end of formed list. Then you link your current node to the last of the left list, and first of the right list. Basic case it, when there is no left or right element, which is the node it self for both. Once all is done, you can link the first and last of the final result. Below is the java code.
static void convertToSortedList(TreeNode T){
TreeNode[] r = convertToSortedListHelper(T);
r[1].next = r[0];
r[0].prev= r[1];
}
static TreeNode[] convertToSortedListHelper(TreeNode T){
TreeNode[] ret = new TreeNode[2];
if (T == null) return ret;
if (T.left == null && T.right == null){
ret[0] = T;
ret[1] = T;
return ret;
}
TreeNode[] left = TreeNode.convertToSortedListHelper(T.left);
TreeNode[] right = TreeNode.convertToSortedListHelper(T.right);
if (left[1] != null) left[1].next = T;
T.prev = left[1];
T.next = right[0];
if (right[0] != null) right[0].prev = T;
ret[0] = left[0]==null? T:left[0];
ret[1] = right[1]==null? T:right[1];
return ret;
}
Add the following method to your Node class
public Node toLinked() {
Node leftmost = this, rightmost = this;
if (right != null) {
right = right.toLinked();
rightmost = right.left;
right.left = this;
}
if (left != null) {
leftmost = left.toLinked();
left = leftmost.left;
left.right = this;
}
leftmost.left = rightmost;
rightmost.right = leftmost;
return leftmost;
}
EDIT By maintaining the invariant that the list returned by toLinked() has the proper form, you can easily get the left- and rightmost nodes in the sublist returned by the recursive call on the subtrees
/* input: root of BST. Output: first node of a doubly linked sorted circular list. **Constraints**: do it in-place. */
public static Node transform(Node root){
if(root == null){
return null;
}
if(root.isLeaf()){
root.setRight(root);
root.setLeft(root);
return root;
}
Node firstLeft = transform(root.getLeft());
Node firstRight = transform(root.getRight());
Node lastLeft = firstLeft == null ? null : firstLeft.getLeft();
Node lastRight= firstRight == null ? null : firstRight.getLeft();
if(firstLeft != null){
lastLeft.setRight(root);
root.setLeft(lastLeft);
if(lastRight == null){
firstLeft.setLeft(root);
}
else{
firstLeft.setLeft(lastRight);
root.setRight(firstRight);
}
}
if(firstRight != null){
root.setRight(firstRight);
firstRight.setLeft(root);
if(lastLeft == null){
root.setLeft(lastRight);
lastRight.setLeft(root);
firstLeft = root;
}
else{
root.setLeft(lastLeft);
lastRight.setRight(firstLeft);
}
}
return firstLeft;
}

Categories