Deleting duplicates in a linked list - java

I can't see my error. I'm using a list where the insert method puts every new element added in order. I'm trying not to use hashtables for this case.
I wrote out a control flow graph, wrote it on paper, and it seems to make sense in those mediums but i'm not able to get the results i'm looking for.
My list: 0,1,1,1,2,4,5,7
It is the exact same after I run it through this method:
public class List {
int value;
List next;
List(int value, List next) {
this.value = value;
this.next = next;
}
}
public void deleteDuplicates() {
List marker = head;
List pointer = marker;
while(marker != null && marker.next != null){
while(pointer.next != null){
if(marker.value == pointer.next.value){
pointer.next = pointer.next.next;
}
else{
pointer = pointer.next;
}
}
marker = marker.next;
}
}

You are not resetting the pointer variable after the end of the inner loop: after marker = marker.next; you should add pointer = marker;
Also Node seems a better name rather than List.

The issue with your code is that you are having two pointers (marker and pointer) but not making any use of the second pointer (pointer). If you are coming across same value you are incrementing the pointer but eventually throwing away pointer without making any use of it.
A more succinct way to eliminate duplicates would be as follows -
List marker=head;
List pointer;
while(marker != null && marker.next != null){
pointer = marker.next;
while(pointer != null && marker.value == pointer.value){ //Skip nodes which have same value
pointer = pointer.next;
}
marker.next = pointer;
marker = marker.next;
}

Related

Keeping head reference while traversing Linked Lists?

I'm revising Linked Lists and in the book I'm using they suggest the following code to search for a specific value:
public ListElement<Integer> find( ListElement<Integer> head, int data ){
ListElement<Integer> elem = head;
while( elem != null && elem.value() != data ){
elem = elem.next();
}
return elem;
}
But, cannot we iterate on head directly?
You can - but then it would be a somewhat misleading piece of code. If I look at a variable called head, I'd expect it to be the head of a list - whereas if I do:
head = head.next();
... then head refers to something which isn't the head of the list. It's always worrying when a variable name implies something that isn't true. It would technically work, but it would be a bad idea.
I would personally write the code more like this:
public ListElement<Integer> find(ListElement<Integer> head, int data) {
for (ListElement<Integer> current = head;
current != null;
current = current.next()) {
if (current.value == data) {
return current;
}
}
// No entry found
return null;
}
That way the "not found" case is more naturally distinct from the "found" case - it would be easier to change it to throw an exception if the value isn't found, for example.

Adding a object to a linked list at the end but always resulting into an error when a 2nd object is passed thru

I'm working on this method with linked list.
It's a method that add's an object at the end of the list.
I've got a problem when adding a second object in the linked list.
It gives me a NullPointerException at the while :
while (this.actual.getNext() != null)
I can't see what's wrong and i've been on this for an hour doing junits tests.
Any help ?
here's the complete code :
public boolean addEnd(T element) {
boolean res = false;
this.actual = this.head;
if (element != null) {
if (this.actual == null) {
this.head= new Node<T>(element);
res = true;
nbElm++;
} else if (!hasElement(element)) {
while (this.actual.getNext() != null) { //Gives me an error NullPointeException
this.actual = this.actual.getNext();
}
Node<T> next = new Node<T>(element);
this.actual.setNext(next);
res = true;
nbElm++;
}
}
return res;
}
Looking at this addEnd method, I think this.actual has no reason of being an instance variable. It should be a local variable of the method. Being an instance variable may cause other methods that use it to interfere with addEnd. I'm guessing hasElement modifies this variable, causing this.actual to become null before the start of your while loop.

Java : Merging two sorted linked lists

I have developed a code to merge two already sorted linked lists in java.
I need help with the following:
How do I retain the value of head node of merged list without using tempNode?
Can this code be better optimized?
public static ListNode mergeSortedListIteration(ListNode nodeA, ListNode nodeB) {
ListNode mergedNode ;
ListNode tempNode ;
if (nodeA == null) {
return nodeB;
}
if (nodeB == null) {
return nodeA;
}
if ( nodeA.getValue() < nodeB.getValue())
{
mergedNode = nodeA;
nodeA = nodeA.getNext();
}
else
{
mergedNode = nodeB;
nodeB = nodeB.getNext();
}
tempNode = mergedNode;
while (nodeA != null && nodeB != null)
{
if ( nodeA.getValue() < nodeB.getValue())
{
mergedNode.setNext(nodeA);
nodeA = nodeA.getNext();
}
else
{
mergedNode.setNext(nodeB);
nodeB = nodeB.getNext();
}
mergedNode = mergedNode.getNext();
}
if (nodeA != null)
{
mergedNode.setNext(nodeA);
}
if (nodeB != null)
{
mergedNode.setNext(nodeB);
}
return tempNode;
}
1: You have to keep a record of the first node, which means you will have to store it in a variable such as tempNode.
2: No. There's not much to optimize here. The process is quite trivial.
There are a few possibilities:
1) Instead of using mergedNode to keep track of the previous node, use nodeA.getNext().getValue() and nodeB.getNext().getValue(). Your algorithm will become more complex and you will have to deal with a few edge cases, but it is possible to eliminate one of your variables.
2) Use a doubly linked-list, and then use either nodeA.getPrev().getValue() and nodeB.getPrev().getValue() instead of mergedNode. You will also have to deal with edge cases here too.
In order to deal with edge cases, you will have to guarantee that your references can not possibly be null before calling getPrev(), getNext() or getValue(), or else you will throw an exception.
Note that the above modifications sacrifice execution time slightly and (more importantly) simplicity in order to eliminate a variable. Any gains would be marginal, and developer time is far more important than shaving a microsecond or two off of your operation.

LinkedLists in Java; making the last node on the list point to the first node rather than contain null

I'm trying to figure out how to write a method that would modify the last node in a linkedlist and change it from null to the first node when passed the first pointer from the linked list.
I tried this which turned into a error:
public void blah()
{
Node p = first;
while (p != null)
{
p = p.link;
}
p.x = p.first;
}
Try this:
public void blah() {
Node p = first;
while (p.link != null) {
p = p.link;
}
p.link = first;
}
Be aware that this will create a circular list, that's what you intend, right? Also, I'm assuming that first is an attribute of the class where blah() resides.
This would do the job for you.
public void blah(Node list){
Node firstNode = list;
while (list.link != null){
list = list.link;
}
list.link = firstNode;
}
The 'first' reference you've used in the code suggests that its a member variable. If you want to read more on Singly Linked lists in Java thoroughly, follow this link.

Java Programming - Circular LinkedList

I am trying to write a java class CircularList which contains the usual Node inner class and the instance variables:
OK, I won't give you the full implementation of the class, but instead I'll give you some advices.
You don't need to hold a reference to the last element. Place a Prev and Next reference to your nodes and your last node will be first.Prev
Besides the fact that circular lists have no end, they are quite the same than regular lists, but where you find the last item like this:
Node tmp = first;
while ( tmp.Next != null )
tmp = tmp.Next;
In a circular list the idea is like this:
Node tmp = first;
while ( tmp.Next != first )
tmp = tmp.Next;
Because you will never find a node pointing to null, unless the list is empty. One final advice, if you need to implement an indexer, remember that in a circular list there is no such thing as index out of range, because
list[count] = list[0] = list[count * k]
Keep that in mind, so calculating your index for those methods can be quite tricky. For positive indexes, the main idea is:
index = index % count;
For negative ones is slightly different. I hope I can help you with my words. If you want an implementations, I believe that there should be a few if you ask Google politely :)
Best of luck!
I'm not sure what your issue is, you seem to have everything needed. The only difference between that linked list and a normal one would be adding to the end.
In a regular linked list you would create a new node and make the last element point to that node. In this case, you change the pointer in the •Last node to point to the new node, and make the new node point to •First.
Removal works in the same way as a normal linked list. Whenever you want to remove a node, you find which other node points to that one (either previous, or in case of removing the first, check •Last) and make it point to wherever the one being deleted was pointing.
If this does not resolve your issue let me know and I'll try to help.
Just noticed someone has already asked the exact same question:
Can I use java.util.LinkedList to construct a circular/cyclic linked list?
Hint... circular list should have next and previous instead of first and last. The logic matters
class Node {
int value;
Node next;
Node prev;
Node(int initialValue) {
value = initialValue;
next = null;
prev = null;
}
public int getValue() {
return this.value;
}
}
class NodeList {
Node pointer;
NodeList() {
pointer = null;
}
public void insertNode(int nodeValue) {
Node newNode = new Node(nodeValue);
if( pointer == null ) {
newNode.next = newNode;
newNode.prev = newNode;
}else if( pointer.next == null && pointer.prev == null && pointer != null ) {
newNode.next = pointer;
newNode.prev = pointer;
pointer.prev = newNode;
pointer.next = newNode;
}
else if( pointer != null ) {
newNode.next = pointer.next;
newNode.prev = pointer;
pointer.next.prev = newNode;
pointer.next = newNode;
}
pointer = newNode;
System.out.println(“Successfully inserted : ” + pointer.getValue());
}
public void printRing( boolean direction ) {
Node tempNode = pointer;
do {
System.out.println( “Value = ” + tempNode.getValue() );
tempNode = direction ? tempNode.next : tempNode.prev;
} while( tempNode.value != pointer.value );
}
}

Categories