Linked List natural mergeSort - java

So Natural mergeSort is a variation on mergeSort that instead of splitting the list into halves, you iterate through the list, make 2 new temp lists that are "naturally sorted" and then sort those 2 lists.
e.g. List = 1, 3, 2, 4, 5, null
The first temp list == 1, 3 because 1 < 3, but 3 is not < 2
The second temp list == 2, 4, 5
Next step is to compare first temp list with second temp list
if( firstTemp > secondTemp)
swap;
My problem comes from creating these 2 separate lists.
When I create the 2 new lists, it's erasing my original list. Also I can't seem to get my counter right for creating the size of the lists. A new list doesn't seem to act like a new list because the counter keeps incrementing from the original list to the new lists.
Like the e.g. above,
ogList.size = 5
then
firstTemp.size = 7
secondTemp.size = 10
When it should be
firstTemp.size = 2
and
secondTemp.size = 3
package mergesortlinkedlist;
public class MergeSortLinkedList {
static LinkedList list = new LinkedList();
public static void main(String[] args) {
//
// start linked list
//
LinkedList.push(list, 1);
LinkedList.push(list, 3);
LinkedList.push(list, 2);
LinkedList.push(list, 4);
LinkedList.push(list, 5);
list.printList(list);
System.out.println("list size = " + list.head.getCounter());
naturalMerge(list);
}
public static void naturalMerge(LinkedList front) {
LinkedList set1 = new LinkedList();
LinkedList set2 = new LinkedList();
LinkedList temp = front;
//get first temp list
while (temp != null) {
if (temp.head.data < temp.head.next.data) {
LinkedList.push(set1, temp.head.data);
temp.head = temp.head.next;
} else {
LinkedList.push(set1, temp.head.data);
temp.head = temp.head.next;
break;
}
}
//get second temp list
while (temp != null) {
if (temp.head.data < temp.head.next.data) {
LinkedList.push(set2, temp.head.data);
temp.head = temp.head.next;
} else {
LinkedList.push(set2, temp.head.data);
temp.head = temp.head.next;
break;
}
}
mergeSwap(set1, set2);
}
public static void mergeSwap(LinkedList set1, LinkedList ){
//template code to swap the naturally sorted temp lists
}
}
}
public class LinkedList {
public Node head;
public static class Node {
public Node next = null;
public Integer data;
public static int counter = 0;
Node() {
}
Node(int d) {
this.data = d;
}
public void setCounter(int n) {
counter += n;
}
public int getCounter() {
return counter;
}
}
public static void push(LinkedList list, int data) {
// Create a new node with given data
Node new_node = new Node(data);
new_node.next = null;
// If the Linked List is empty,
// then make the new node as head
if (list.head == null) {
list.head = new_node;
new_node.setCounter(1);
} else {
// Else traverse till the last node
// and insert the new_node there
Node last = list.head;
while (last.next != null) {
last = last.next;
}
// Insert the new_node at last node
last.next = new_node;
new_node.setCounter(1);
}
// Return the list by head
//return list;
}
I'm just wondering if this version of my code is possible for creating separate lists for natural mergeSort. Am I able to use this code to make new lists without destroying the original list?
Ultimately, I want my list = 1,2,3,4,5,null

Ok well I changed some things, it's not able to do recurssive calls, which makes me think the logic isn't working right, but I'm still able to sort the list.
Instead of calling
naturalMerge(list);
after swapping nodes, I do it from main. The only reason is because for some reason I get a null pointer exception.
I'd like to come back to this and make it work better, but for now it'll probably do for getting my assignment turned in.
package mergesortlinkedlist;
public class MergeSortLinkedList {
// static Node first = new Node();
static LinkedList list = new LinkedList();
public static void main(String[] args) {
// start linked list
list.add(list, 1);
list.add(list, 5);
list.add(list, 3);
list.add(list, 4);
list.add(list, 2);
list.add(list, 100);
list.add(list, 76);
list.add(list, -6);
list.printList(list);
naturalMerge(list);
list.printList(list);
naturalMerge(list);
list.printList(list);
naturalMerge(list);
list.printList(list);
}
public static void naturalMerge(LinkedList front) {
LinkedList set1 = new LinkedList();
LinkedList set2 = new LinkedList();
LinkedList temp = front;
int size1 = 0;
int sortCounter = 0; //if sortCounter != 0, then there is more to sort
//get first temp list
while (temp.head.data != null) {
if (temp.head.data < temp.head.next.data) {
set1.add(set1, temp.head.data);
size1++;
temp.head = temp.head.next;
} else {
set1.add(set1, temp.head.data);
size1++;
temp.head = temp.head.next;
break;
}
}
//get second temp list
while (temp.head != null) {
if (temp.head.next == null) {
set2.add(set2, temp.head.data);
temp.head = temp.head.next;
break;
}
if (temp.head.data < temp.head.next.data) {
set2.add(set2, temp.head.data);
temp.head = temp.head.next;
} else {
set2.add(set2, temp.head.data);
temp.head = temp.head.next;
break;
}
}
mergeSwap(set1, set2, size1);
}
public static void mergeSwap(LinkedList set1, LinkedList set2, int size1) {
System.out.println();
LinkedList temp = set1;
LinkedList temp2 = set2;
while (temp.head != null && temp2.head != null) {
if (temp.head.data < temp2.head.data) {
list.add(list, temp.head.data);
temp.head = temp.head.getNext(); //increment temp
} else {
list.add(list, temp2.head.data);
temp2.head = temp2.head.getNext(); //increment temp2
}
//if one list is empty, break loop and add remaining nodes
if (temp.head == null || temp2.head == null) {
break;
}
}
//check which list is empty, and add the remaining nodes to original list
if (temp.head == null) {
while (temp2.head != null) {
list.add(list, temp2.head.data);
temp2.head = temp2.head.getNext();
}
} else {
while (temp.head != null) {
list.add(list, temp.head.data);
temp.head = temp.head.getNext();
}
}
//naturalMerge(list); //this call breaks the code, but why? How is it any different from the method call in main?
}
}

Related

LinkedList Custom Implementation Faster than Java LinkedList

I've recently started Cracking the Code Interview and I just got to LinkedLists. I did problem 2.1 to remove duplicate entries from the book's implementation of LinkedList.
When I time the removal of dupes, I see the book's implementation is faster than Java LinkedList.
I've implemented four dupe removal methods, each with a different parameter. The book's LinkedList implementation is referred to as Node.
static void removeDupes(LinkedList<Integer> list) {
HashSet<Integer> integerHashSet = new HashSet<>();
for (int i = 0; i < list.size(); i++) {
if (integerHashSet.contains(list.get(i))) {
list.remove(list.get(i));
} else {
integerHashSet.add(list.get(i));
}
}
}
static void removeDupes(ArrayList<Integer> list) {
HashSet<Integer> integerHashSet = new HashSet<>();
for (int i = 0; i < list.size(); i++) {
if (integerHashSet.contains(list.get(i))) {
list.remove(list.get(i));
} else {
integerHashSet.add(list.get(i));
}
}
}
static void removeDupes(Node currentNode) {
HashSet<Integer> integerHashSet = new HashSet<>();
while(currentNode != null) {
if (integerHashSet.contains(currentNode.data)) {
currentNode.prev.next = currentNode.next;
if (currentNode.next != null) {
currentNode.next.prev = currentNode.prev;
}
} else {
integerHashSet.add(currentNode.data);
}
currentNode = currentNode.next;
}
}
static void removeDupesNoBuffer(Node currentNode) {
while (currentNode != null) {
Node runnerNode = currentNode;
while(runnerNode.next != null) {
if (runnerNode.next.data == currentNode.data) {
runnerNode.next = runnerNode.next.next;
if (runnerNode.next != null) {
runnerNode.next.prev = runnerNode;
}
} else {
runnerNode = runnerNode.next;
}
}
currentNode = currentNode.next;
}
}
Book's LinkedList implementation:
public class Node {
Node prev;
Node next;
int data;
Node(int d) {
data = d;
}
void add(int d) {
Node newNode = new Node(d);
Node currentNode = this;
while (currentNode.next != null) {
currentNode = currentNode.next;
}
currentNode.next = newNode;
newNode.prev = currentNode;
}
}
Each List or Node, I populated with a length of 100000, where each odd index was 0 and everything else was unique.
My results were:
Node: 18ms
Node No Buffer: 5154ms
LinkedList: 2734ms
ArrayList: 1392ms
What am I not understanding?
EDIT:
When I swapped the remove dupes with the LinkedList parameter to an enhanced for loop as pointed out by the comments and solution, it became just as fast.
static void removeDupes(LinkedList<Integer> list) {
HashSet<Integer> integerHashSet = new HashSet<>();
for(Integer i : list) {
if (integerHashSet.contains(i)) {
list.remove(i);
} else {
integerHashSet.add(i);
}
}
}
The reason is that your doing it inefficently. If you use indices to iterate over a linked list the list has to count each node reference to find the correct one. And then it acts on that one.
Try it like this and see the difference. Counting even values of a linked list of N items. The second iteration will be much faster.
First, a indexed for loop.
List<Integer> list1 = new LinkedList<>();
Random r = new Random();
int N = 100_000;
for(int i = 0; i < N; i++) {
list1.add(r.nextInt(10000));
}
// copy the list
List<Integer> list2 = new LinkedList<>(list1);
System.out.println("Starting list1");
int sumEvens = 0;
for(int i = 0; i < list1.size(); i++) {
if (list1.get(i) % 2 == 0) {
sumEvens++;
}
}
System.out.printf("There were %d even values%n", sumEvens);
Now an enhanced forloop which uses an iterator.
System.out.println("Starting list2");
sumEvens = 0;
for(int i : list2) {
if ( i%2 == 0) {
sumEvens++;
}
}
System.out.printf("There were %d even values%n", sumEvens);
Finally, Arraylists are fast at accessing but slow at deleting. This is because when an item is deleted, all subsequent items must be copied up one cell to close the gap. But a linked list can delete an item by simply having the previous node point to the following node. So how a list is to be used drives the selection of the list implementation.

How can I insert an Item at the end of the List?

I am working on a project for my Data Structures class that asks me to write a class to implement a linked list of ints.
Use an inner class for the Node.
Include the methods below.
Write a tester to enable you to test all of the methods with whatever data you want in any order.
I have a method called "public void insertAt(int index, int item)". This method is meant to "Insert an item at position index, where index is passed to the method" I have my code for this method down below. When I insert an Item at an Index it works unless it's the last item in the list. When I try to insert an item at the end of the list it replaces the last item and the item that was there before is erased when It shouldn't. For example, If I had a list: "[9, 8, 15, 7, 5, 15, 19, 6, 19, 2]" and I want to insert the number "90" and the last index it should look like [9, 8, 15, 7, 5, 15, 19, 6, 19, 90, 2] but instead I get [9, 8, 15, 7, 5, 15, 19, 6, 19, 90]. How can I fix this in my code so if I was to insert an item at the tail it would move the Item I want inserted to be placed before the tail?
import java.util.Random;
import java.util.Scanner;
public class LinkedListOfInts {
Node head;
Node tail;
private class Node {
int value;
Node nextNode;
public Node(int value, Node nextNode) {
this.value = value;
this.nextNode = nextNode;
}
}
public LinkedListOfInts(LinkedListOfInts other) {
Node tail = null;
for (Node n = other.head; n != null; n = n.nextNode) {
if (tail == null)
this.head = tail = new Node(n.value, null);
else {
tail.nextNode = new Node(n.value, null);
tail = tail.nextNode;
}
}
}
public LinkedListOfInts(int[] other) {
Node[] nodes = new Node[other.length];
for (int index = 0; index < other.length; index++) {
nodes[index] = new Node(other[index], null);
if (index > 0) {
nodes[index - 1].nextNode = nodes[index];
}
}
head = nodes[0];
}
public LinkedListOfInts(int N, int low, int high) {
Random random = new Random();
for (int i = 0; i < N; i++)
this.addToFront(random.nextInt(high - low) + low);
}
public void addToFront(int x) {
head = new Node(x, head);
}
public void insertAt(int index, int item) {
Node temp = head;
Node prev = null;
int i = 0;
for (Node ptr = head; ptr != null; ptr = ptr.nextNode) {
if (index == i) {
Node newItem = new Node(item, null);
prev.nextNode = newItem;
if (temp.nextNode != null) {
newItem.nextNode = temp;
}
}
if (temp.nextNode != null) {
prev = temp;
temp = temp.nextNode;
i++;
}
}
}
public String toString() {
String result = "";
for (Node ptr = head; ptr != null; ptr = ptr.nextNode) {
if (!result.isEmpty()) {
result += ", ";
}
result += ptr.value;
}
return "[" + result + "]";
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
LinkedListOfInts list = new LinkedListOfInts(10, 1, 20);
boolean done = false;
while (!done) {
System.out.println("1. Insert At");
System.out.println("2. toString");
switch (input.nextInt()) {
case 1:
System.out.println("Insert an Item to a certain Index on the List");
list.insertAt(input.nextInt(), input.nextInt());
break;
case 2:
System.out.println("toString");
System.out.println(list.toString());
break;
}
}
}
}
You have an error in this line:
if (temp.nextNode != null) {
newItem.nextNode = temp;
}
Right there, temp is your last element, be it 2. Your new element ( 90) will only have temp assigned, it temp has a pointer to the next element (temp.nextNode != null) Because temp has no next element, nextNode won't be assigned at all. In fact, you can omit this check at all cause if temp was null , you would only assign null to the nextNode of the newItem which would be fine.
Also, make sure to handle other issues in your implementation, such as adding the element at index 0. At the moment, in the beginning you set Node prev = null; and then in the first iteration of the loop prev is null and you would end up with the NPE whenever you try to add the element at index 0.
To fix this, you need to change this section:
if (index == i) {
Node newItem = new Node(item, null);
prev.nextNode = newItem;
newItem.nextNode = temp;
}
into
if (index == i) {
Node newItem = new Node(item, null);
if (prev != null) {
prev.nextNode = newItem;
}
newItem.nextNode = temp;
}
Writing good unit tests may help you with the robust implementation and will help you solve this kind of issues much quicker. Check out this question to see how to write unit tests in java.

Reverse even numbers (Only) from given Singly Linked List

I want to reverse even numbers in a singly linked list in java, but I face some difficulty to get the correct output.
For example,
input : 2, 18, 24, 3, 5, 7, 9, 6, 12
the method should reverse the even numbers only which are {2,18,24} and {6,12}
the correct output : 24 , 18 ,2 , 3 , 5 ,7 , 9 , 12 , 6
But,my output: 24 18 3 5 7 9 12 6 which it is wrong
the main method
public static void main(String[] args) throws Exception {
SLL<Integer> p = new SLL<Integer>();
int[] e = { 2, 18, 24, 3, 5, 7, 9, 6, 12,5 ,4 ,3 ,2,6,8};
for (int i = 0; i < e.length; i++) {
p.addToHead(e[i]);
}
p = reverse(p);
p.printAll();
}
This is the method (that doesn't work correctly)
public static SLL<Integer> reverse(SLL<Integer> p) {
SLL<Integer> returnList = new SLL<Integer>();
Stack<Integer> stk = new Stack<Integer>();
for (SLLNode tmp = p.getHead(); tmp != null; tmp = tmp.next) {
if ((((Integer) tmp.info) % 2) != 0) {
returnList.addToHead((Integer) tmp.info);
p.deleteFromHead();
} else if ((((Integer) tmp.info) % 2) == 0) {
stk.push((Integer) tmp.info);
p.deleteFromHead();
}
if (stk.getLSize() >= 2) {
while (!(stk.isEmpty())) {
returnList.addToHead((Integer) stk.pop());
}
}
}
return returnList;
}
this is the SLLNode class
public class SLLNode<T> {
public T info;
public SLLNode<T> next;
public SLLNode() {
this(null,null);
}
public SLLNode(T el) {
this(el,null);
}
public SLLNode(T el, SLLNode<T> ptr) {
info = el;
next = ptr;
}
}
this is the SLL class
public class SLL<T> {
protected SLLNode<T> head, tail;
public SLL() {
head = tail = null;
}
public boolean isEmpty() {
return head == null;
}
public void addToHead(T el) {
head = new SLLNode<T>(el, head);
if (tail == null)
tail = head;
}
public SLLNode getHead(){
return head;
}
public void addToTail(T el) {
if (!isEmpty()) {
tail.next = new SLLNode<T>(el);
tail = tail.next;
} else
head = tail = new SLLNode<T>(el);
}
public T deleteFromHead() { // delete the head and return its info;
if (isEmpty())
return null;
T el = head.info;
if (head == tail) // if only one node on the list;
head = tail = null;
else
head = head.next;
return el;
}
public T deleteFromTail() { // delete the tail and return its info;
if (isEmpty())
return null;
T el = tail.info;
if (head == tail) // if only one node in the list;
head = tail = null;
else { // if more than one node in the list,
SLLNode<T> tmp; // find the predecessor of tail;
for (tmp = head; tmp.next != tail; tmp = tmp.next)
;
tail = tmp; // the predecessor of tail becomes tail;
tail.next = null;
}
return el;
}
public void delete(T el) { // delete the node with an element el;
if (!isEmpty())
if (head == tail && el.equals(head.info)) // if only one
head = tail = null; // node on the list;
else if (el.equals(head.info)) // if more than one node on the list;
head = head.next; // and el is in the head node;
else { // if more than one node in the list
SLLNode<T> pred, tmp;// and el is in a nonhead node;
for (pred = head, tmp = head.next; tmp != null
&& !tmp.info.equals(el); pred = pred.next, tmp = tmp.next)
;
if (tmp != null) { // if el was found;
pred.next = tmp.next;
if (tmp == tail) // if el is in the last node;
tail = pred;
}
}
}
public void printAll() {
for (SLLNode<T> tmp = head; tmp != null; tmp = tmp.next)
System.out.print(tmp.info + " ");
}
public boolean isInList(T el) {
SLLNode<T> tmp;
for (tmp = head; tmp != null && !tmp.info.equals(el); tmp = tmp.next)
;
return tmp != null;
}
public int length() {
int length = 0;
for (SLLNode tmp = head; tmp != null; tmp = tmp.next) {
length += 1;
}
return length;
}
Running your reverse method gives me a different output to what you see. So, I suspect you got your output from slightly different code.
I get : 24, 6, 9, 7, 5, 3, 2, 18
In your reverse method you start adding even numbers to your returnList when you have 2 on the stack. If you want to reverse all even numbers you need to wait until you have all the continuous even numbers on the stack. Or in other words, when you get an odd number, or there are no numbers left, you can pop all the even numbers back off the stack..
I think you should also use addTail rather than addHead.
So something like
public static SLL<Integer> reverse(SLL<Integer> p) {
SLL<Integer> returnList = new SLL<Integer>();
Stack<Integer> stk = new Stack<Integer>();
for (SLLNode tmp = p.getHead(); tmp != null; tmp = tmp.next) {
if ((((Integer) tmp.info) % 2) != 0) {
// add any stacked even numbers
while (!(stk.isEmpty())) {
returnList.addToTail((Integer) stk.pop());
}
// add the odd number
returnList.addToTail((Integer) tmp.info);
} else if ((((Integer) tmp.info) % 2) == 0) {
System.out.println("even " + tmp.info);
stk.push((Integer) tmp.info);
}
}
// add any remaining even numbers from the stack
while (!(stk.isEmpty())) {
returnList.addToTail((Integer) stk.pop());
}
return returnList;
}
I made it using list of python, I just wanted to know whether I could write this program without using a linked list or not. The complexities may be high, but it is just an experimental implementation which works
arr = [2,18,24,3,5,7,9,6,12]
arr_final = []
temp = []
for i in arr:
if i%2 == 0:
temp.append(i)
else:
if temp!=[]:
temp.reverse()
for j in temp:
arr_final.append(j)
temp = []
arr_final.append(i)
if temp!=[]:
temp.reverse()
for j in temp:
arr_final.append(j)
temp = []
print(arr_final)

Linkedlist polynomial why my output only print first term

I just wrote a program that add two polynomial linked-list. my output only prints first term of the polynomials.
I cannot figure out what bug is. I want to get some help here. could someone tell what's wrong with my code.
public void addNode(int cof, int exp) {
PNode node = new PNode(cof, exp);
if (first == null) {
first = last = node;
return;
}
last.next = node;
last = node;
}
public PolynomialLinkedList add(PolynomialLinkedList s) {
PolynomialLinkedList sum = new PolynomialLinkedList();
//implement this method
PNode list1 = first;
PNode list2 = s.first;
while (list1 != null && list2 != null) {
if (list1.exp == list2.exp) {
sum.addNode(list1.coe + list2.coe, list1.exp);
list1 = list1.next;
list2 = list2.next;
} else if (list1.exp > list2.exp) {
sum.addNode(list1.coe, list1.exp);
list1 = list1.next;
} else if (list2.exp > list1.exp) {
sum.addNode(list2.coe, list2.exp);
list2 = list2.next;
}
}
return sum;
}
If one of the lists finishes first, the rest of the items in other list are ignored and are not getting added to the sum.
Add additional loops
while(list1 != null) {
sum.addNode(list1.coe,list1.exp);
list1=list1.next;
}
and
while(list2 != null) {
sum.addNode(list2.coe,list2.exp);
list2=list2.next;
}

Remove duplicates from an unsorted linked list

import java.util.*;
/*
* Remove duplicates from an unsorted linked list
*/
public class LinkedListNode {
public int data;
public LinkedListNode next;
public LinkedListNode(int data) {
this.data = data;
}
}
public class Task {
public static void deleteDups(LinkedListNode head){
Hashtable<Integer, Boolean> table=new Hashtable<Integer, Boolean>();
LinkedListNode previous=null;
//nth node is not null
while(head!=null){
//have duplicate
if(table.containsKey(head.data)){
//skip duplicate
previous.next=head.next;
}else{
//put the element into hashtable
table.put(head.data,true);
//move to the next element
previous=head;
}
//iterate
head=head.next;
}
}
public static void main (String args[]){
LinkedList<Integer> list=new LinkedList<Integer>();
list.addLast(1);
list.addLast(2);
list.addLast(3);
list.addLast(3);
list.addLast(3);
list.addLast(4);
list.addLast(4);
System.out.println(list);
LinkedListNode head=new LinkedListNode(list.getFirst());
Task.deleteDups(head);
System.out.println(list);
}
}
The result: [1, 2, 3, 3, 3, 4, 4]
[1, 2, 3, 3, 3, 4, 4]
It does not eliminate the duplicates.
Why doesn't the method work?
Iterate through the linked list,
adding each element to a hash table. When we discover a duplicate element, we remove the element and continue iterating. We can do this all in one pass since we are using a linked list.
The following solution takes O(n) time, n is the number of element in the linked list.
public static void deleteDups (LinkedListNode n){
Hashtable table = new Hashtable();
LinkedListNode previous = null;
while(n!=null){
if(table.containsKey(n.data)){
previous.next = n.next;
} else {
table.put(n.data, true);
previous = n;
}
n = n.next;
}
}
The solution you have provided does not modify the original list.
To modify the original list and remove duplicates, we can iterate with two pointers. Current: which iterates through LinkedList, and runner which checks all subsequent nodes for duplicates.
The code below runs in O(1) space but O(N square) time.
public void deleteDups(LinkedListNode head){
if(head == null)
return;
LinkedListNode currentNode = head;
while(currentNode!=null){
LinkedListNode runner = currentNode;
while(runner.next!=null){
if(runner.next.data == currentNode.data)
runner.next = runner.next.next;
else
runner = runner.next;
}
currentNode = currentNode.next;
}
}
Reference : Gayle laakmann mcdowell
Here's two ways of doing this in java. the method used above works in O(n) but requires additional space. Where as the second version runs in O(n^2) but requires no additional space.
import java.util.Hashtable;
public class LinkedList {
LinkedListNode head;
public static void main(String args[]){
LinkedList list = new LinkedList();
list.addNode(1);
list.addNode(1);
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.addNode(2);
list.print();
list.deleteDupsNoStorage(list.head);
System.out.println();
list.print();
}
public void print(){
LinkedListNode n = head;
while(n!=null){
System.out.print(n.data +" ");
n = n.next;
}
}
public void deleteDups(LinkedListNode n){
Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
LinkedListNode prev = null;
while(n !=null){
if(table.containsKey(new Integer(n.data))){
prev.next = n.next; //skip the previously stored references next node
}else{
table.put(new Integer(n.data) , true);
prev = n; //stores a reference to n
}
n = n.next;
}
}
public void deleteDupsNoStorage(LinkedListNode n){
LinkedListNode current = n;
while(current!=null){
LinkedListNode runner = current;
while(runner.next!=null){
if(runner.next.data == current.data){
runner.next = runner.next.next;
}else{
runner = runner.next;
}
}
current = current.next;
}
}
public void addNode(int d){
LinkedListNode n = new LinkedListNode(d);
if(this.head==null){
this.head = n;
}else{
n.next = head;
head = n;
}
}
private class LinkedListNode{
LinkedListNode next;
int data;
public LinkedListNode(int d){
this.data = d;
}
}
}
You can use the following java method to remove duplicates:
1) With complexity of O(n^2)
public void removeDuplicate(Node head) {
Node temp = head;
Node duplicate = null; //will point to duplicate node
Node prev = null; //prev node to duplicate node
while (temp != null) { //iterate through all nodes
Node curr = temp;
while (curr != null) { //compare each one by one
/*in case of duplicate skip the node by using prev node*/
if (curr.getData() == temp.getData() && temp != curr) {
duplicate = curr;
prev.setNext(duplicate.getNext());
}
prev = curr;
curr = curr.getNext();
}
temp = temp.getNext();
}
}
Input:1=>2=>3=>5=>5=>1=>3=>
Output:1=>2=>3=>5=>
2)With complexity of O(n) using hash table.
public void removeDuplicateUsingMap(Node head) {
Node temp = head;
Map<Integer, Boolean> hash_map = new HashMap<Integer, Boolean>(); //create a hash map
while (temp != null) {
if (hash_map.get(temp.getData()) == null) { //if key is not set then set is false
hash_map.put(temp.getData(), false);
} else { //if key is already there,then delete the node
deleteNode(temp,head);
}
temp = temp.getNext();
}
}
public void deleteNode(Node n, Node start) {
Node temp = start;
if (n == start) {
start = null;
} else {
while (temp.getNext() != n) {
temp = temp.getNext();
}
temp.setNext(n.getNext());
}
}
Input:1=>2=>3=>5=>5=>1=>3=>
Output:1=>2=>3=>5=>
Ans is in C . first sorted link list sort() in nlog time and then deleted duplicate del_dip() .
node * partition(node *start)
{
node *l1=start;
node *temp1=NULL;
node *temp2=NULL;
if(start->next==NULL)
return start;
node * l2=f_b_split(start);
if(l1->next!=NULL)
temp1=partition(l1);
if(l2->next!=NULL)
temp2=partition(l2);
if(temp1==NULL || temp2==NULL)
{
if(temp1==NULL && temp2==NULL)
temp1=s_m(l1,l2);
else if(temp1==NULL)
temp1=s_m(l1,temp2);
else if(temp2==NULL)
temp1=s_m(temp1,l2);
}
else
temp1=s_m(temp1,temp2);
return temp1;
}
node * sort(node * start)
{
node * temp=partition(start);
return temp;
}
void del_dup(node * start)
{
node * temp;
start=sort(start);
while(start!=NULL)
{
if(start->next!=NULL && start->data==start->next->data )
{
temp=start->next;
start->next=start->next->next;
free(temp);
continue;
}
start=start->next;
}
}
void main()
{
del_dup(list1);
print(list1);
}
Try this it is working for delete the duplicate elements from your linkedList
package com.loknath.lab;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
public class Task {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<Integer>();
list.addLast(1);
list.addLast(2);
list.addLast(3);
list.addLast(3);
list.addLast(3);
list.addLast(4);
list.addLast(4);
deleteDups(list);
System.out.println(list);
}
public static void deleteDups(LinkedList<Integer> list) {
Set s = new HashSet<Integer>();
s.addAll(list);
list.clear();
list.addAll(s);
}
}
I think you can just use one iterator current to finish this problem
public void compress(){
ListNode current = front;
HashSet<Integer> set = new HashSet<Integer>();
set.add(current.data);
while(current.next != null){
if(set.contains(current.next.data)){
current.next = current.next.next; }
else{
set.add(current.next.data);
current = current.next;
}
}
}
Here is a very easy version.
LinkedList<Integer> a = new LinkedList<Integer>(){{
add(1);
add(1);
}}
Set<Integer> set = new HashSet<Integer>(a);
a = new LinkedList<Integer>(set);
Very concise. Isn't it?
The first problem is that
LinkedListNode head=new LinkedListNode(list.getFirst());
does not actually initialize head with the contents of list. list.getFirst() simply returns the Integer 1, and head contains 1 as its only element. You would have to initialize head by looping through list in order to get all of the elements.
In addition, although
Task.deleteDups(head)
modifies head, this leaves list completely unchanged—there is no reason why the changes to head should propagate to list. Therefore, to check your method, you would have to loop down head and print out each element, rather than printing out list again.
Try This.Its working.
// Removing Duplicates in Linked List
import java.io.*;
import java.util.*;
import java.text.*;
class LinkedListNode{
int data;
LinkedListNode next=null;
public LinkedListNode(int d){
data=d;
}
void appendToTail(int d){
LinkedListNode newnode = new LinkedListNode(d);
LinkedListNode n=this;
while(n.next!=null){
n=n.next;
}
n.next=newnode;
}
void print(){
LinkedListNode n=this;
System.out.print("Linked List: ");
while(n.next!=null){
System.out.print(n.data+" -> ");
n=n.next;
}
System.out.println(n.data);
}
}
class LinkedList2_0
{
public static void deletenode2(LinkedListNode head,int d){
LinkedListNode n=head;
// If It's head node
if(n.data==d){
head=n.next;
}
//If its other
while(n.next!=null){
if(n.next.data==d){
n.next=n.next.next;
}
n=n.next;
}
}
public static void removeDuplicateWithBuffer(LinkedListNode head){
LinkedListNode n=head;
LinkedListNode prev=null;
Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
while(n!=null){
if(table.containsKey(n.data)){
prev.next=n.next;
}
else{
table.put(n.data,true);
prev=n;
}
n=n.next;
}
}
public static void removeDuplicateWithoutBuffer(LinkedListNode head){
LinkedListNode currentNode=head;
while(currentNode!=null){
LinkedListNode runner=currentNode;
while(runner.next!=null){
if(runner.next.data==currentNode.data){
runner.next=runner.next.next;
}
else
runner=runner.next;
}
currentNode=currentNode.next;
}
}
public static void main(String[] args) throws java.lang.Exception {
LinkedListNode head=new LinkedListNode(1);
head.appendToTail(1);
head.appendToTail(3);
head.appendToTail(2);
head.appendToTail(3);
head.appendToTail(4);
head.appendToTail(5);
head.print();
System.out.print("After Delete: ");
deletenode2(head,4);
head.print();
//System.out.print("After Removing Duplicates(with buffer): ");
//removeDuplicateWithBuffer(head);
//head.print();
System.out.print("After Removing Duplicates(Without buffer): ");
removeDuplicateWithoutBuffer(head);
head.print();
}
}
here are a couple other solutions (slightly different from Cracking coding inerview, easier to read IMO).
public void deleteDupes(Node head) {
Node current = head;
while (current != null) {
Node next = current.next;
while (next != null) {
if (current.data == next.data) {
current.next = next.next;
break;
}
next = next.next;
}
current = current.next;
}
}
public void deleteDupes(Node head) {
Node current = head;
while (current != null) {
Node next = current.next;
while (next != null) {
if (current.data == next.data) {
current.next = next.next;
current = current.next;
next = current.next;
} else {
next = next.next;
}
}
current = current.next;
}
}
It's simple way without HashSet or creation Node.
public String removeDuplicates(String str) {
LinkedList<Character> chars = new LinkedList<Character>();
for(Character c: str.toCharArray()){
chars.add(c);
}
for (int i = 0; i < chars.size(); i++){
for (int j = i+1; j < chars.size(); j++){
if(chars.get(j) == chars.get(i)){
chars.remove(j);
j--;
}
}
}
return new String(chars.toString());
}
And to verify it:
#Test
public void verifyThatNoDuplicatesInLinkedList(){
CodeDataStructures dataStructures = new CodeDataStructures();
assertEquals("abcdefghjk", dataStructures.removeDuplicates("abcdefgabcdeaaaaaaaaafabcdeabcdefgabcdbbbbbbefabcdefghjkabcdefghjkghjkhjkabcdefghabcdefghjkjfghjkabcdefghjkghjkhjkabcdefghabcdefghjkj")
.replace(",", "")
.replace("]", "")
.replace("[", "")
.replace(" ", ""));
}
LinkedList<Node> list = new LinkedList<Node>();
for(int i=0; i<list.size(); i++){
for(int j=0; j<list.size(); j++){
if(list.get(i).data == list.get(j).data && i!=j){
if(i<j){
list.remove(j);
if(list.get(j)!= null){
list.get(j-1).next = list.get(j);
}else{
list.get(j-1).next = null;
}
}
else{
if(i>j){
list.remove(i);
if(list.get(i) != null){
list.get(j).next = list.get(i);
}else{
list.get(j).next = null;
}
}
}
}
}
}
/**
*
* Remove duplicates from an unsorted linked list.
*/
public class RemoveDuplicates {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<String>();
list.add("Apple");
list.add("Grape");
list.add("Apple");
HashSet<String> set = removeDuplicatesFromList(list);
System.out.println("Removed duplicates" + set);
}
public static HashSet<String> removeDuplicatesFromList(LinkedList<String> list){
HashSet<String> set = new LinkedHashSet<String>();
set.addAll(list);
return set;
}
}
Below code implements this without needing any temporary buffer. It starts with comparing first and second nodes, if not a match, it adds char at first node to second node then proceeds comparing all chars in second node to char at third node and so on. After comperison is complete, before leaving the node it clears everything that is added and restores its old value which resides at node.val.char(0)
F > FO > FOL > (match found, node.next = node.next.next) > (again match, discard it) > FOLW > ....
public void onlyUnique(){
Node node = first;
while(node.next != null){
for(int i = 0 ; i < node.val.length(); i++){
if(node.val.charAt(i) == node.next.val.charAt(0)){
node.next = node.next.next;
}else{
if(node.next.next != null){ //no need to copy everything to the last element
node.next.val = node.next.val + node.val;
}
node.val = node.val.charAt(0)+ "";
}
}
node = node.next;
}
}
All the solutions given above looks optimised but most of them defines custom Node as a part of solution. Here is a simple and practical solution using Java's LinkedList and HashSet which does not confine to use the preexisting libraries and methods.
Time Complexity : O(n)
Space Complexity: O(n)
#SuppressWarnings({ "unchecked", "rawtypes" })
private static LinkedList<?> removeDupsUsingHashSet(LinkedList<?> list) {
HashSet set = new HashSet<>();
for (int i = 0; i < list.size();) {
if (set.contains(list.get(i))) {
list.remove(i);
continue;
} else {
set.add(list.get(i));
i++;
}
}
return list;
}
This also preserves the list order.
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(1);
linkedList.add(2);
linkedList.add(2);
linkedList.add(3);
linkedList.add(4);
linkedList.add(5);
linkedList.add(6);
deleteElement(linkedList);
System.out.println(linkedList);
}
private static void deleteElement(LinkedList<Integer> linkedList) {
Set s = new HashSet<Integer>();
s.addAll(linkedList);
linkedList.clear();
linkedList.addAll(s);
}
This is my Java version
// Remove duplicate from a sorted linked list
public void removeDuplicates() {
Node current = head;
Node next = null;
/* Traverse list till the last node */
while (current != null) {
next = current;
/*
* Compare current node with the next node and keep on deleting them until it
* matches the current node data
*/
while (next != null && current.getValue() == next.getValue()) {
next = next.getNext();
}
/*
* Set current node next to the next different element denoted by temp
*/
current.setNext(next);
current = current.getNext();
}
}
1.Fully Dynamic Approach
2.Remove Duplicates from LinkedList
3.LinkedList Dynamic Object based creation
Thank you
import java.util.Scanner;
class Node{
int data;
Node next;
public Node(int data)
{
this.data=data;
this.next=null;
}
}
class Solution
{
public static Node insert(Node head,int data)
{
Node p=new Node(data);
if(head==null)
{
head=p;
}
else if(head.next==null)
{
head.next=p;
}
else
{
Node start=head;
while(start.next!=null)
{
start=start.next;
}
start.next=p;
return head;
//System.out.println();
}
return head;
}
public static void display(Node head)
{
Node start=head;
while(start!=null)
{
System.out.print(start.data+" ");
start=start.next;
}
}
public static Node remove_duplicates(Node head)
{
if(head==null||head.next==null)
{
return head;
}
Node prev=head;
Node p=head.next;
while(p!=null)
{
if(p.data==prev.data)
{
prev.next=p.next;
p=p.next;
}
else{
prev=p;
p=p.next;
}
}
return head;
}
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
Node head=null;
int T=sc.nextInt();
while(T-->0)
{
int ele=sc.nextInt();
head=insert(head,ele);
}
head=remove_duplicates(head);
display(head);
}
}
input:
5
1 1 2 3 3
output:
1 2 3

Categories

Resources