I want to remove duplicates from sorted linked list {0 1 2 2 3 3 4 5}.
`
public Node removeDuplicates(Node header)
{
Node tempHeader = null;
if(header != null)
tempHeader = header.next;
else return header;
Node prev = header;
if((tempHeader == null)) return header ;
while(tempHeader != null)
{
if(tempHeader.data != prev.data)
{
prev.setNext(tempHeader);
}
tempHeader = tempHeader.next;
}
prev = header;
printList(prev);
return tempHeader;
}
`
prev.setNext(tempHeader) is not working correctly inside the while loop. Ideally when prev = 2 and tempHeader = 3, prev.next should be node with data = 3.
Printlist function just takes header pointer and prints the list.
Node definition is given below.
public class Node
{
int data;
Node next;
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
The loop is sorted, so you know that duplicates are going to sit next to each other. If you want to edit the list in place then, you've got to have two list pointers (which you do). The one you call tempHeader and prev, and you've got to advance them both in the the list as you go (which I don't see in the code). Otherwise, if you don't advance the prev pointer as you go, then you're always comparing the element under tempHeader to the first item in the list, which is not correct.
An easier way to do this, however, is to build a new list as you go. Simply remember the value of the last item that you appended to the list. Then if the one that you're about to insert is the same then simply don't insert it, and when you're done, just return your new list.
I can give you 2 suggestions for the above suggestion
1) Convert the linked List to Set, that will eliminate the duplicates and
Back from Set to the Linked list
Code to get this done would be
linkedList = new LinkedList<anything>(new HashSet<anything>(origList));
2) You can use LinkedHashSet, if you dont want any duplicates
In this case no return value is needed.
public void removeDuplicates(Node list) {
while (list != null) {
// Walk to next unequal node:
Node current = list.next;
while (current != null && current.data.equals(list.data)) {
current = current.next;
}
// Skip the equal nodes:
list.next = current;
// Take the next unequal node:
list = current;
}
}
public ListNode removeDuplicateElements(ListNode head) {
if (head == null || head.next == null) {
return null;
}
if (head.data.equals(head.next.data)) {
ListNode next_next = head.next.next;
head.next = null;
head.next = next_next;
removeDuplicateElements(head);
} else {
removeDuplicateElements(head.next);
}
return head;
}
By DoublyLinked List and using HashSet,
public static void deleteDups(Node n) {
HashSet<Integer> set = new HashSet<Integer>();
Node previous = null;
while (n != null) {
if (set.contains(n.data)) {
previous.next = n.next;
} else {
set.add(n.data);
previous = n;
}
n = n.next;
}
}
doublylinkedList
class Node{
public Node next;
public Node prev;
public Node last;
public int data;
public Node (int d, Node n, Node p) {
data = d;
setNext(n);
setPrevious(p);
}
public Node() { }
public void setNext(Node n) {
next = n;
if (this == last) {
last = n;
}
if (n != null && n.prev != this) {
n.setPrevious(this);
}
}
public void setPrevious(Node p) {
prev = p;
if (p != null && p.next != this) {
p.setNext(this);
}
}}
Related
I'm on HackerRank and I need to remove duplicate items from a sorted linked list. I passed all the cases except for two of them which the input is something like: 10001102034
So my program takes to seconds to complete and exceed the time. How can I do my code more efficiently, I heard about using square root but I don't know how to use it. Any guide is appreciate. Here is my code.
private static Node removeDuplicates(Node head) {
/* Another reference to head */
Node current = head;
Node next;
/* Traverse list till the last node */
while (current != null && current.next != null) {
if (current.data == current.next.data) {
next = current.next.next;
if (next == null) {
current.next = null;
break;
}
current.next = next;
} else {
current = current.next;
}
}
return head;
}
Again. It works but takes too much times with longer numbers.
You should replace condition if (current.data == current.next.data) with while loop and use break 'label':
out:
while (current != null && current.next != null) {
while (current.data == current.next.data) {
next = current.next.next;
if (next == null) {
current.next = null;
break out;
}
current.next = next;
}
current = current.next;
}
You can't use the square root because when u want to remove duplicates from a list you have to check all the list .
The square root technique is used for searching in a sorted list.
But for your question if you can improve the runtime on that your code in O(n^2) but if you change your code to use hashtable you can make it O(n).
import java.util.HashSet;
public class removeDuplicates
{
static class node
{
int val;
node next;
public node(int val)
{
this.val = val;
}
}
/* Function to remove duplicates from a
unsorted linked list */
static void removeDuplicate(node head)
{
// Hash to store seen values
HashSet<Integer> hs = new HashSet<>();
/* Pick elements one by one */
node current = head;
node prev = null;
while (current != null)
{
int curval = current.val;
// If current value is seen before
if (hs.contains(curval)) {
prev.next = current.next;
} else {
hs.add(curval);
prev = current;
}
current = current.next;
}
}
/* Function to print nodes in a given linked list */
static void printList(node head)
{
while (head != null)
{
System.out.print(head.val + " ");
head = head.next;
}
}
I hope this will help you.
I made a singly linked list from scratch in java. The code is as follows:
public class SingleLinkedList<Item>
{
private Node head;
private int size;
private class Node
{
Item data;
Node next;
public Node(Item data)
{
this.data = data;
this.next = null;
}
public Node(Item data, Node next)
{
this.data = data;
this.next = next;
}
//Getters and setters
public Item getData()
{
return data;
}
public void setData(Item data)
{
this.data = data;
}
public Node getNext()
{
return next;
}
public void setNext(Node next)
{
this.next = next;
}
}
public SingleLinkedList()
{
head = new Node(null);
size = 0;
}
public void add(Item data)
{
Node temp = new Node(data);
Node current = head;
while(current.getNext() != null)
{
current = current.getNext();
}
current.setNext(temp);
size++;
}
public void add(Item data, int index)
{
Node temp = new Node(data);
Node current = head;
for(int i=0; i<index && current.getNext() != null; i++)
{
current = current.getNext();
}
temp.setNext(current.getNext());
current.setNext(temp);
size++;
}
public Item get(int index)
{
if(index <= 0)
{
return null;
}
Node current = head;
for(int i=1; i<index; i++)
{
if(current.getNext() == null)
{
return null;
}
current = current.getNext();
}
return current.getData();
}
public boolean remove(int index)
{
if(index < 1 || index > size())
{
return false;
}
Node current = head;
for(int i=1; i<index; i++)
{
if(current.getNext() == null)
{
return false;
}
current = current.getNext();
}
current.setNext(current.getNext().getNext());
size--;
return true;
}
public String toString()
{
Node current = head.getNext();
String output = "";
while(current != null)
{
output+=current.getData().toString()+" ";
current = current.getNext();
}
return output;
}
public int size()
{
return size;
}
public void reverse()
{
Node current = head;
Node prevNode = null;
Node nextNode;
while(current!=null)
{
nextNode = current.getNext();
current.setNext(prevNode);
prevNode = current;
current = nextNode;
System.out.println(prevNode.getData());
}
head = prevNode;
}
}
As you can see, I added the reverse function in the class only.
But when I tried actually using the class it gave NullPointerException after I tried to reverse it.
To check the functionality I used another class called TEST. The code is as follows:
public class TEST
{
public static void main(String[] args)
{
SingleLinkedList<Integer> list = new SingleLinkedList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list.toString());
list.reverse();
System.out.println(list.toString());
}
}
The output is as follows:
1 2 3 4 5
null
1
2
3
4
5
Exception in thread "main" java.lang.NullPointerException
at SingleLinkedList.toString(SingleLinkedList.java:129)
at TEST.main(TEST.java:20)
I tried to print the value of prevNode to check whether its not taking values...but it is.
What to do?
Actually, your reverse method looks fine.
The problem is your toString() method.
When you create a new list, you create an initial element whose data is null.
Your toString method skips that first element, so it works fine as long as you don't reverse the list.
But when you reverse the list, that null element becomes the last element, and when you call output+=current.getData().toString()+" "; for that last element when current.getData() is null, you get NullPointerException.
You have several options :
Your reverse method can keep the initial null element first (i.e. reverse the rest of the list, but keep the head the same). This way toString can remain unchanged.
Eliminate the initial null element. Then your toString method doesn't have to skip anything.
Keeping the null element first :
public void reverse()
{
Node current = head.getNext();
Node prevNode = null;
Node nextNode;
while(current!=null)
{
nextNode = current.getNext();
current.setNext(prevNode);
prevNode = current;
current = nextNode;
System.out.println(prevNode.getData());
}
head.setNext(prevNode);
}
The problem is in your SingleLinkedList.java toString() method
Try below it is working fine
public String toString() {
Node current = head;
String output = "";
while (current != null) {
// output += current.getData().toString() + " ";
output += String.valueOf(current.getData()) + " ";
current = current.getNext();
}
return output;
}
while(current!=null)
This is your problem. When you hit the last node the 'next' node you get is actually null.
Try changing it to
while(current!=null&¤t.getNext()!=null)
EDIT: Actually not sure that solution will work. Try putting a conditional at the end of your loop that says:
if(current.getNext()==null)
break;
EDIT (again :/):
ok sorry I wasn't thinking straight.
change that final if statement to:
if(current.getNext()==null){
current.setNext(prevNode);
break;
}
The actual nullpointer is in the toString. Here's what you do:
Change the while conditional to
while(current != null&¤t.getData()!=null)
Because otherwise if current points to null then you get an exception.
That was exhausting.
I was trying to reverse a linked list using recursion. I got the solution, but can't get it to work for below question found on internet.
Reverse a linked list using recursion but function should have void
return type.
I was able to implement the function with return type as Node. Below is my solution.
public static Node recursive(Node start) {
// exit condition
if(start == null || start.next == null)
return start;
Node remainingNode = recursive(start.next);
Node current = remainingNode;
while(current.next != null)
current = current.next;
current.next = start;
start.next = null;
return remainingNode;
}
I cannot imagine if there will be such a solution to this problem.
Any suggestions ?
Tested, it works (assuming you have your own implementation of a linked list with Nodes that know the next node).
public static void reverse(Node previous, Node current) {
//if there is next node...
if (current.next != null) {
//...go forth and pwn
reverse(current, current.next);
}
if (previous == null) {
// this was the start node
current.next= null;
} else {
//reverse
current.next= previous;
}
}
You call it with
reverse(null, startNode);
public void recursiveDisplay(Link current){
if(current== null)
return ;
recursiveDisplay(current.next);
current.display();
}
static StringBuilder reverseStr = new StringBuilder();
public static void main(String args[]) {
String str = "9876543210";
reverse(str, str.length() - 1);
}
public static void reverse(String str, int index) {
if (index < 0) {
System.out.println(reverseStr.toString());
} else {
reverseStr.append(str.charAt(index));
reverse(str, index - 1);
index--;
}
}
This should work
static void reverse(List list, int p) {
if (p == list.size() / 2) {
return;
}
Object o1 = list.get(p);
Object o2 = list.get(list.size() - p - 1);
list.set(p, o2);
list.set(list.size() - p - 1, o1);
reverse(list, p + 1);
}
though to be efficient with LinkedList it should be refactored to use ListIterator
I am not familiar with Java, but here is a C++ version. After reversing the list, the head of list is still preserved, which means that the list can still be accessible from the old list head List* h.
void reverse(List* h) {
if (!h || !h->next) {
return;
}
if (!h->next->next) {
swap(h->value, h->next->value);
return;
}
auto next_of_next = h->next->next;
auto new_head = h->next;
reverse(h->next);
swap(h->value, new_head->value);
next_of_next->next = new_head;
h->next = new_head->next;
new_head->next = nullptr;
}
Try this code instead - it actually works
public static ListElement reverseListConstantStorage(ListElement head) {
return reverse(null,head);
}
private static ListElement reverse(ListElement previous, ListElement current) {
ListElement newHead = null;
if (current.getNext() != null) {
newHead = reverse(current, current.getNext());
} else {//end of the list
newHead=current;
newHead.setNext(previous);
}
current.setNext(previous);
return newHead;
}
public static Node recurse2(Node node){
Node head =null;
if(node.next == null) return node;
Node previous=node, current = node.next;
head = recurse2(node.next);
current.next = previous;
previous.next = null;
return head;
}
While calling the function assign the return value as below:
list.head=recurse2(list.head);
The function below is based on the chosen answer from darijan, all I did is adding 2 lines of code so that it'd fit in the code you guys want to work:
public void reverse(Node previous, Node current) {
//if there is next node...
if (current.next != null) {
//...go forth and pwn
reverse(current, current.next);
}
else this.head = current;/*end of the list <-- This line alone would be the fix
since you will now have the former tail of the Linked List set as the new head*/
if (previous == null) {
// this was the start node
current.next= null;
this.tail = current; /*No need for that one if you're not using a Node in
your class to represent the last Node in the given list*/
} else {
//reverse
current.next= previous;
}
}
Also, I've changed it to a non static function so then the way to use it would be: myLinkedList.reverse(null, myLinkedList.head);
Here is my version - void ReverseWithRecursion(Node currentNode)
- It is method of LinkListDemo Class so head is accessible
Base Case - If Node is null, then do nothing and return.
If Node->Next is null, "Make it head" and return.
Other Case - Reverse the Next of currentNode.
public void ReverseWithRecursion(Node currentNode){
if(currentNode == null) return;
if(currentNode.next == null) {head = currentNode; return;}
Node first = currentNode;
Node rest = currentNode.next;
RevereseWithRecursion(rest);
first.next.next = first;
first.next = null;
}
You Call it like this -
LinkListDemo ll = new LinkListDemo(); // assueme class is available
ll.insert(1); // Assume method is available
ll.insert(2);
ll.insert(3);
ll.ReverseWithRecursion(ll.head);
Given that you have a Node class as below:
public class Node
{
public int data;
public Node next;
public Node(int d) //constructor.
{
data = d;
next = null;
}
}
And a linkedList class where you have declared a head node, so that it can be accessed by the methods that you create inside LinkedList class. The method 'ReverseLinkedList' takes a Node as an argument and reverses the ll.
You may do a dry run of the code by considering 1->2 as the linkedList. Where node = 1, node.next = 2.
public class LinkedList
{
public Node? head; //head of list
public LinkedList()
{
head = null;
}
public void ReverseLinkedList(Node node)
{
if(node==null)
{
return;
}
if(node.next==null)
{
head = node;
return;
}
ReverseLinkedList(node.next); // node.next = rest of the linkedList
node.next.next = node; // consider node as the first part of linkedList
node.next = null;
}
}
The simplest method that I can think of it's:
public static <T> void reverse( LinkedList<T> list )
{
if (list.size() <= 1) {
return;
}
T first = list.removeFirst();
reverse( list);
list.addLast( first );
}
Right now my Linked list is in a queue form. My LList class holds two fields called head and tail which are the head and tail of the list. Head and tail are LNode objects, a LNode is an element of the list that holds a int value, and it's previous LNode and next LNode.
Here's my LNode class:
class LNode{
private int val;
private LNode next;//not recursive
private LNode prev;
public LNode(int v, LNode n, LNode p){
next = n;
prev = p;
val = v;
}
public int getVal(){
return val;
}
public LNode getNext(){
return next;
}
public LNode getPrev(){
return prev;
}
public void setVal(int v){
val = v;
}
public void setNext(LNode n){
next = n;
}
public void setPrev(LNode p){
prev = p;
}
}
I am trying to make a delete method in my LList class so that it takes a value and delete the LNode that has that value. My problem is, I don't know how I would deal with the case where the LNode I'm trying to delete is the head or the tail.
public void delete(int v){
if(head.getVal()==v){//delete head
head = head.getNext();
head.setPrev(null);
}
else if(tail.getVal()==v){//delete tail
System.out.println("boiboi");
tail = tail.getPrev();
tail.setNext(null);
}
else{//delete other element
LNode tmp = head;
while(tmp.getVal()!=v){
tmp = tmp.getNext();
}
tmp.getPrev().setNext(tmp.getNext());
tmp.getNext().setPrev(tmp.getPrev());
}
}
What i have tried is to set the new head's previous LNode to be null, but Java doesn't allow that. So what should I do?
Thank you.
Your code looks okay to me, except in the case that the value you're removing is the sole value - in which case you want to end up with both the head and the tail as null. I suspect all you need to do is change the head case:
if (head.getVal() == v) {
head = head.getNext();
if (head != null) {
head.setPrev(null);
} else {
// If head.getNext() returns null, then tail must have been equal to head.
tail = null;
}
}
You should also check for the empty list situation first:
if (head == null) {
return;
}
And in your general case, handle the situation where the value isn't found:
while (tmp != null && tmp.getVal() != v) {
tmp = tmp.getNext();
}
if (tmp == null) {
return;
}
I am implementing my own linked list in Java. The node class merely has a string field called "name" and a node called "link". Right now I have a test driver class that only inserts several names sequentially. Now, I am trying to write a sorting method to order the nodes alphabetically, but am having a bit of trouble with it. I found this pseudocode of a bubblesort from someone else's post and tried to implement it, but it doesn't fully sort the entries. I'm not really quite sure why. Any suggestions are appreciated!
private void sort()
{
//Enter loop only if there are elements in list
boolean swapped = (head != null);
// Only continue loop if a swap is made
while (swapped)
{
swapped = false;
// Maintain pointers
Node curr = head;
Node next = curr.link;
Node prev = null;
// Cannot swap last element with its next
while (next != null)
{
// swap if items in wrong order
if (curr.name.compareTo(next.name) < 0)
{
// notify loop to do one more pass
swapped = true;
// swap elements (swapping head in special case
if (curr == head)
{
head = next;
Node temp = next.link;
next.link = curr;
curr.link = temp;
curr = head;
}
else
{
prev.link = curr.link;
curr.link = next.link;
next.link = curr;
curr = next;
}
}
// move to next element
prev = curr;
curr = curr.link;
next = curr.link;
}
}
}
I spent some minutes eyeballing your code for errors but found none.
I'd say until someone smarter or more hard working comes along you should try debugging this on your own. If you have an IDE like Eclipse you can single-step through the code while watching the variables' values; if not, you can insert print statements in a few places and hand-check what you see with what you expected.
UPDATE I
I copied your code and tested it. Apart from the fact that it sorts in descending order (which may not be what you intended) it worked perfectly for a sample of 0, 1 and 10 random nodes. So where's the problem?
UPDATE II
Still guessing what could be meant by "it doesn't fully sort the entries." It's possible that you're expecting lexicographic sorting (i.e. 'a' before 'B'), and that's not coming out as planned for words with mixed upper/lower case. The solution in this case is to use the String method compareToIgnoreCase(String str).
This may not be the solution you're looking for, but it's nice and simple. Maybe you're lazy like I am.
Since your nodes contain only a single item of data, you don't really need to re-shuffle your nodes; you could simply exchange the values on the nodes while leaving the list's structure itself undisturbed.
That way, you're free to implement Bubble Sort quite simply.
you should use the sorting procedures supplied by the language.
try this tutorial.
Basically, you need your element class to implement java.lang.Comparable, in which you will just delegate to obj.name.compareTo(other.name)
you can then use Collections.sort(yourCollection)
alternatively you can create a java.util.Comparator that knows how to compare your objects
To obtain good performance you can use Merge Sort.
Its time complexity is O(n*log(n)) and can be implemented without memory overhead for lists.
Bubble sort is not good sorting approach. You can read the What is a bubble sort good for? for details.
This may be a little too late. I would build the list by inserting everything in order to begin with because sorting a linked list is not fun.
I'm positive your teacher or professor doesn't want you using java's native library. However that being said, there is no real fast way to resort this list.
You could read all the nodes in the order that they are in and store them into an array. Sort the array and then relink the nodes back up. I think the Big-Oh complexity of this would be O(n^2) so in reality a bubble sort with a linked list is sufficient
I have done merge sort on the singly linked list and below is the code.
public class SortLinkedList {
public static Node sortLinkedList(Node node) {
if (node == null || node.next == null) {
return node;
}
Node fast = node;
Node mid = node;
Node midPrev = node;
while (fast != null && fast.next != null) {
fast = fast.next.next;
midPrev = mid;
mid = mid.next;
}
midPrev.next = null;
Node node1 = sortLinkedList(node);
Node node2 = sortLinkedList(mid);
Node result = mergeTwoSortedLinkedLists(node1, node2);
return result;
}
public static Node mergeTwoSortedLinkedLists(Node node1, Node node2) {
if (null == node1 && node2 != null) {
return node2;
} else if (null == node2 && node1 != null) {
return node1;
} else if (null == node1 && null == node2) {
return null;
} else {
Node result = node1.data <= node2.data ? node1 : node2;
Node prev1 = null;
while (node1 != null && node2 != null) {
if (node1.data <= node2.data) {
prev1 = node1;
node1 = node1.next;
} else {
Node next2 = node2.next;
node2.next = node1;
if (prev1 != null) {
prev1.next = node2;
}
node1 = node2;
node2 = next2;
}
}
if (node1 == null && node2 != null) {
prev1.next = node2;
}
return result;
}
}
public static void traverseNode(Node node) {
while (node != null) {
System.out.print(node + " ");
node = node.next;
}
System.out.println();
}
public static void main(String[] args) {
MyLinkedList ll1 = new MyLinkedList();
ll1.insertAtEnd(10);
ll1.insertAtEnd(2);
ll1.insertAtEnd(20);
ll1.insertAtEnd(4);
ll1.insertAtEnd(9);
ll1.insertAtEnd(7);
ll1.insertAtEnd(15);
ll1.insertAtEnd(-3);
System.out.print("list: ");
ll1.traverse();
System.out.println();
traverseNode(sortLinkedList(ll1.start));
}
}
The Node class:
public class Node {
int data;
Node next;
public Node() {
data = 0;
next = null;
}
public Node(int data) {
this.data = data;
}
public int getData() {
return this.data;
}
public Node getNext() {
return this.next;
}
public void setData(int data) {
this.data = data;
}
public void setNext(Node next) {
this.next = next;
}
#Override
public String toString() {
return "[ " + data + " ]";
}
}
The MyLinkedList class:
public class MyLinkedList {
Node start;
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (start == null) {
start = newNode;
return;
}
Node traverse = start;
while (traverse.getNext() != null) {
traverse = traverse.getNext();
}
traverse.setNext(newNode);
}
public void traverse() {
if (start == null)
System.out.println("List is empty");
else {
Node tempNode = start;
do {
System.out.print(tempNode.getData() + " ");
tempNode = tempNode.getNext();
} while (tempNode != null);
System.out.println();
}
}
}