Non-destructive recursive intersect of two singly linked lists - java

I want to take two singly linked lists (this function is called from within one) and create a third singly linked list that contains all intersections between the two. So if p=[0,1,2,3] and q=[1,3,7,9] then out=[1,3], while leaving the old lists intact.
As you can see I need to declare "out" in two places. But if I hit the declaration by calling the function again, it naturally wipes what I previously wrote to it. I really can't figure out how to avoid it.
Singly linked lists can be generated with http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html . first is my header.
public List intersection(List l) {
if(first.data == l.first.data) {
List lTail = new List(l.first.next);
List tail = new List(first.next);
List out = new List(new Node(first.data, null)); //Bad idea #1
// System.out.println(out);
return tail.intersection(lTail);
} else if (first.data > l.first.data && l.first.next != null) {
List lTail = new List(l.first.next);
return intersection(lTail);
} else if (first.data < l.first.data && first.next != null) {
List tail = new List(first.next);
return tail.intersection(l);
} else { //When both lists are at the end position
List out = new List(new Node(0, null)); // Bad idea #2
return out;
}
}

List<T> p = new LinkedList<T>();
p.add...
...
List<T> q = new LinkedList<T>();
q.add...
...
List<T> intersection = new LinkedList<T>(p);
intersection.retainAll(q);
Now intersection contains only elements, which are in both lists, while lists theirselves remain untouched.

Related

Returning a new LinkedList (custom built)

I am trying to return a new linkedList of numbers after filtering. What I have here modifies the original list it's invoked on in-place and a toString() on the original list fails afterwards. How do I return a new list without interfering with the original one this method is called on?
public CustomLinkedList filterEvenInts() {
Node current = data;
// note: returned list should have values in the order they appeared in the original list.
if (current == null) {
return new CustomLinkedList();
}
Node prev = current;
while (prev.next != null) {
if (prev.next.value % 2 != 0) {
prev.next = prev.next.next;
} else {
prev = prev.next;
}
}
// delete current if odd too
if (current.next.value % 2 != 0) {
current = current.next;
prev = current;
}
CustomLinkedList newList = new CustomLinkedList();
newList.data = prev;
return newList;
}
From what I understood you would probably have to copy the list somehow first. Just creating a new one and setting the data of the new one to the old one won't work as you are still referencing the same object. One way to do it would be to go through each node of the old list, create a new node from the value of the old node and add the new node to the new list. Editing the new list then doesn't affect the old list.

Clone elements of linkedlist to a new list

I was asked this question in an interview to clone the elements of linked list A into a new list. This was my approach but I was rejected. I did get it right but I am not sure why the interviewer didn't like my approach. Any tips/advise to what I could have done better? List A has elements [10,12,11,4,5,6] let's assume.
public class CopyLinkedListElements {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.head = new Node(10);
linkedList.head.next = new Node(12);
linkedList.head.next.next = new Node(11);
linkedList.head.next.next.next = new Node(4);
linkedList.head.next.next.next.next = new Node(5);
linkedList.head.next.next.next.next.next = new Node(6);
cloneOrgList(linkedList.head);
}
public static void cloneOrgList(Node head) {
Node current = head;
Node newHead = new Node(current.data);
Node prev = newHead;
System.out.println(prev.data);
while(current != null && current.next != null) {
current = current.next;
Node newNode = new Node(current.data);
prev.next = newNode;
prev = newNode;
System.out.println(prev.data);
}
}
}
In addition to what was mentioned about return values, the loop is a bit messy. It can be improved like this:
public static Node cloneLinkedList(Node head) {
Node oldCurrent = head;
Node newHead = new Node(oldCurrent.data);
Node newCurrent = newHead;
while ((oldCurrent = oldCurrent.next) != null) {
newCurrent.next = new Node(oldCurrent.data);
newCurrent = newCurrent.next;
}
return newHead;
}
If the interviewer used the word "clone" and not "copy" he or she might have wanted to know if you know how to properly clone objects in Java. IF that was the case, you needed to create a cloneable class. The basic recipe for this is to implement the Cloneable marker interface and override Object's clone method.
public class MyClass implements Cloneable {
// Details of MyClass omitted
// Because Java supports covariant return types, the return type
// for the overridden clone method is the same as the class (i.e. MyClass)
// Also, the method needs to be made public instead of protected.
#Override
public MyClass clone() {
try {
return (MyClass) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError("Something went wrong. This isn't supposed to happen");
}
}
}
If he or she just wanted a copy, an approach like the one you showed should've been OK, except for what has been already mentioned: Your function failed to return the copy. So, in essence, the method is useless.
Lastly, since your original post stated "clone the elements of linked list", you could've done call Linked List clone method
LinkedList<SomeClass> original = new LinkedList<>();
...
LinkedList<SomeClass> clone = (LinkedList<SomeClass>) original.clone();
Again, if the interviewer wanted you to copy the contents, you could've done one of the following:
Collections.copy(dest, source)
dest.addAll(source)
List<String> dest = source.stream().collect(Collectors.toList());
Lastly, the third alternative was the interviewer wanted you to get into cloning vs copying objects in Java, in which case you would've demonstrated both. In the future, ask the interviewer to clarify and restate the question in your own words to get confirmation that you understood the question correctly BEFORE you jump into coding. From your code, it is clear you misunderstood the interviewer.
You need to clone the list such that new references and values are returned. This is not happening in the cloneOrgList method. It doesn't return anything and the scope of the node it operates on is limited to the method itself.
You need to do something like
public LinkedList cloneOrgList(LinkedList orig) {
Node origCurr = orig.head;
LinkedList copy = new LinkedList();
Node newCurr = new Node(origCurr.data);
copy.head = newCurr;
while (origCurr.next != null) {
origCurr = origCurr.next;
newCurr.next = new Node(origCurr.data);
newCurr = newCurr.next;
}
return copy;
}
I think He was expecting to use the clone() method.
Please have a look at the official doc.Javadoc
Sample Code:
package com.raushan.testmind;
import java.util.LinkedList;
public class TestMain {
public static void main(String args[]) {
// Creating an empty LinkedList
LinkedList<Integer> list = new LinkedList<Integer>();
// Use add() method to add elements in the list
list.add(10);
list.add(12);
list.add(11);
list.add(4);
list.add(5);
list.add(6);
// Displaying the list
System.out.println("First LinkedList:" + list);
// Creating another linked list and copying
LinkedList sec_list = new LinkedList();
sec_list = (LinkedList) list.clone();
// Displaying the other linked list
System.out.println("Second LinkedList is:" + sec_list);
}
}

Singly Linked List merge list

I have a method that takes in two generic type Singly Link lists the purpose of the method is to merge the two Singly Link lists into a single new list. But the new list cannot have duplicate values. My code already creates the merged list but it won't remove the duplicate item. There seems to be an issue with the removal part of the code in System.out.println("duplicate:) this part shows that the while loop found a duplicate item but it will not remove. Can some one help me out?
//# param mergeList method combines two Singly Linked lists into one while also removing any duplicate elements. (Incomplete will not remove dupilcates.)
public static <T extends Comparable<T>> SinglyLinkedList<T> mergeLists(SinglyLinkedList<T> list1, SinglyLinkedList<T> list2) {
//new list to merge both parameter lists
SinglyLinkedList<T> fin = new SinglyLinkedList<>();
//node variables pointers
SLLNode temp;
SLLNode l1 = list1.getHead();
SLLNode l2 = list2.getHead();
//while loop to traverse list 1 and add to fin list
while(l1 != null){
temp = l1;
fin.append(temp);
l1 = l1.getNext();
}//close while
//While loop to traverse list 2 and add to fin list
while(l2 != null){
temp = l2;
fin.append(temp);
l2 = l2.getNext();
}//close while
//start of duplicate removal
//create node variables and new no duplicate link list
SLLNode removaltemp = null ,removaltemp2 = null , duplicate = null;
SLLNode pointer= null;
SinglyLinkedList<T> last = new SinglyLinkedList<>();
//Set Nodes
removaltemp = fin.getHead();
pointer = fin.getHead();
last.append(pointer);
//while loop to check head with body
while(removaltemp!= null){
removaltemp2 = removaltemp;
System.out.println("Hello");
//while loop to check body with head
while(removaltemp2.getNext() != null ){
System.out.println("Hi");
//if statement for element removal
if(removaltemp.getData().equals(removaltemp2.getNext().getData())){
System.out.println("duplicate");
duplicate = removaltemp2.getNext();
removaltemp2 = removaltemp2.getNext().getNext();
System.gc();
}// close if
//if not duplicate
else if(removaltemp2 != removaltemp2.getNext()) {
removaltemp2 = removaltemp2.getNext();
}//close else if
}//close nested while loop
//assign next head to loop
pointer= pointer.getNext();
removaltemp = removaltemp.getNext();
}//close while loop
//return statement
return last;
}//close merge method

How to remove from an immutable linked list?

I need to make a linked list using a remove() method, which takes a parameter, e, a generic stand in, and removes the linked node which contains e, then the method returns a new Linked list containing all elements except e.
I have no idea how to implement this and the farthest I have gotten is this:
public Set<E> remove(E e) {
LinkedNode<E> current = null;
if(!this.contains(e)) {//if this list doesnt contain e, return this
return this;
} else {//otherwise go through this set and if it contains e return new set w/out it
for(E j:this) {
if(j.equals(e)) {
current = new LinkedNode<E>(j,current);
}
}
}
Set<E> newSet = new LinkedSet<E>(current);
for(E i:newSet) {
System.out.print(i +", ");
}
return newSet;
}
this code uses an iterator so the enhanced for loop works, but it returns sets with the wrong info. I think this might be because the tail end of the new set I want still has the link to the end of the old list, but this is just a guess.
The last output I got was:d, b, a, c, e, b, d, a, c, e, b, d, a,
and the input was:c,a,d,b,e
I was trying to remove c
Assuming you are returning remaining elements from remove() method you can add every element which is not e:
public Set<E> remove(E e) {
Set<E> newSet = new LinkedSet<E>();
for(E j : this) {
if (!j.equals(e)) {
newSet.add(j);
}
}
return newSet;
}
Assume that there are no dublicates in your list (because actually return type is a set) or at least we need to remove only first occurency.
We could copy elements of current list to new list before 'e' position and use elements after 'e' as tail for both lists. In this way we would copy just part of list, there will be shared elements now. For immutable collection it's ok, but you need be careful with other LinkedList methods implementations.
public Set<E> remove(E e) {
if (!this.contains(e)) {
return this;
}
final LinkedNode<E> head = new LinkedNode<E>(this.head);
// Copy elements of current list to new list before 'e' position
LinkedNode<E> current = this.head, newListCurrent = head;
while (!e.equals(current.next)) {
newListCurrent.next = new LinkedNode<E>(current.next);
newListCurrent = newListCurrent.next;
current = current.next;
}
// Now current.next is element to remove. Link tail of new list to tail of current list
newListCurrent.next = current.next.next;
return new LinkedList<E>(head);
}
It's like pseudocode, but i need full code of your LinkedList and LinkedNode to use them correctly. I've not enought reputitation to ask about it in comment ))

Linked List Structure in Java

i have a question about circularly linked lists. My linked list object has two references, first and last, and the next node of the last reference is first. I want to write a method that inserts a node into the end of the list.
void insertLast(int k) {
Node a = new Node(k);
if (first == null) {
first = last = a;
} else {
last.after = a;
a.after = first;
}
last = a
}
Is something like this possible? Have I made a mistake?
Yes, it is.
let the current last point to the new one (last.setNext(newNode))
let the new one point to the first (newNode.setNext(first))
set the last to be the new node (last = newNode)

Categories