Implementing Linked List in JAVA (Reverse without using iterator) - java

I am trying to implement the linkedList class, adding a method reverse(int n) to reverse the linked list. For example, I have a linked list { A -> B -> C -> D -> E). When I call reverse(4), the linked list will become D-->C-->B-->A-->E.
I am trying to avoid using iterator, constructing new node and copying the data value. Does anyone have idea how to do it? I know there was a post about reversing linked list but that one is reversing the entire linked list.
Thank you so much for the help!

Since you don't provide your implementation of the LinkedList, i can only provide the general idea:
The complete list can be reversed by simply swaping the pointers to the previous node and the next node and updating the fields for the last and first node.
void reverse()
node tmp = first
first = last
last = tmp
while(tmp.next != null)
node swap = tmp.next
tmp.next = tmp.previous
tmp.previous = swap
tmp = swap
I'll leave it to you to add the bounds

Related

JAVA Immutablilty, Copying a Linked List

I am tasked with creating a Linked List class in Java that MUST be immutable. This has been accomplished exactly the same as on here:
https://www.geeksforgeeks.org/linked-list-set-1-introduction/
Among other methods, I need an addToList method that adds a value or multiple values to the tail of the Linked List. Since the Linked List is immutable, adding to it should create a copy of the Linked List (i.e. a new LinkedList object with the same contents) and only add the desired values to the newly created copy.
The copy function is where I need help. Below is the copyList function, partially completed. I am traversing each Node in the LinkedList and printing out the data successfully. Now I need to assign that data to the corresponding element in the clonedList (the new copy). Please see the image below.
public LinkedList<T> copyList(LinkedList<T> toCopy) {
Node n = toCopy.head;
LinkedList clonedList = new LinkedList<T>();
while(n != null) {
System.out.println("Copying: " + n.data);
/*code here(?) to assign elements to clonedList,
but how?
*/
n = n.next;
}
return clonedList;
}
I'm not much for Java, but can't you just do
clonedList.add(n.data)
in your while loop to create a deep copy?
If you don't need a deep copy, you should just be able to set the head of the cloned list to that of the original, e.g.:
LinkedList<T> clonedList = new LinkedList<>();
clonedList.head = toCopy.head;
Otherwise, construct a new Node on each loop iteration and add it to the cloned list. It sounds to me like you have your own LinkedList implementation without an add method, so either write one or replace the method call in the example.
Node<T> n = toCopy.head;
LinkedList<T> clonedList = new LinkedList<>();
while(n != null) {
Node<T> nClone = new Node<>(toCopy.data);
clonedList.add(nClone);
n = n.next;
}
Also, this method should probably either be a constructor or a static method. It doesn't make sense to require an instance for a method that doesn't modify the list's state.

How to create deep copy of Linked List that maintain same order

I got asked the following question at a job interview that I could not figure out. You are given a Linked List of the following Node elements:
class Node {
int value;
Node next; // points to next element in list
Node random; // points to one random element of list
}
Say you have a Linked List of these nodes (say 20 nodes) where "next" points to the next element and "random" points to one other element of the list (meaning, can point to one specific but randomly chosen element in the list). I.e., 1st element's "random" can point to node #5, Node 2nd element's random can point to node #9, etc.
Question: How do you create a brand new Linked List that is a deep copy of this list of Nodes but maintains the same order and same linkages for both "random" and "next"?
In other words, if one traverses this new list using any of these 2 pointers the order of traversal would be the same.
The other topic some people referenced would clone the same pointers via default clone and that would not address this challenge.
Loop all Nodes and put all nodes into a HashMap with the Node as key and a new Node instance as value.
Map<Node, Node> nodeMap = new HashMap<>();
...
nodeMap.put(currentNode, new Node();
Now you again iterate over all your "old" nodes by just looping through node.next and for each node you copy the nodes such that you are referencing the value of the map instead the old node itself.
Node newNode = nodeMap.get(currentNode);
newNode.value = currentNode.value;
newNode.next = nodeMap.get(currentNode.next);
newNode.random = nodeMap.get(currentNode.random);
After that you should have an exact copy without duplicated instances.
import java.util.*;
public class Solution {
HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null)
return null;
if (map.containsKey(head))
return map.get(head);
RandomListNode node = new RandomListNode(head.label);
map.put(head, node);
node.next = copyRandomList(head.next);
node.random = copyRandomList(head.random);
return node;
}
}
After searching online for a while I found this problem with an answer. Pretty tricky. They present this main solution:
copy every node, i.e., duplicate every node, and insert it to the list
copy random pointers for all newly created nodes
break the list to two
See here: http://www.programcreek.com/2012/12/leetcode-copy-list-with-random-pointer/

Remove node from linked list recursively

Given the head of a linked list and the int to search for as parameters, I need a method that will remove the first occurrence of this number in the list, and return the modified list. however i cannot modify the original list. I know how to remove the node from the list, but im not sure how i would keep the original list intact since this has to be done recursively. below is the method
** initially M is the original list. I dont know that it will still be the same list after calling the method again...?
MyList removeNumber(MyList m, int removee){
The idea is that the resulting structure will be a "Y": a two-headed list (actually a simple graph).
One branch of the Y is the original list. The other is your new list with removed node. The vertical stalk of the Y is what's after the element you remove. It's common to both lists. Here's some ascii art with the Y turned on its side showing a list of 1 to 5 with 3 removed.
new -> 1 -> 2 ------\
v
original -> 1 -> 2 -> 3 -> 4 -> 5 -> null
Thinking recursively is all about defining a problem in terms of a smaller version of itself plus a fixed bit of work. And you need a base case (or maybe several).
A linked list is itself a recursive structure:
A list is either empty or it's an element linked by its "next" reference to a list.
Note this defines a list using a smaller list. The base case is the empty list. The fixed bit is the element.
Read this definition a few times, then see how it translates the code:
class MyList {
int value; // the element at the head of this list
MyList next; // the rest of the list
MyList(int value, MyList next) {
this.value = value;
this.next = next;
}
}
The base case "empty list" is just a null reference. The element removal problem expressed recursively using the same pattern becomes:
A copy of a list with an element removed is either a) the rest of the list following the head in the case that the element to be removed is the head or b) a copy of the current node followed by a copy the rest of the list with the desired element removed.
Here I'm defining a "copy of a list with one element removed" using a smaller version of the same thing. Case a) is the base case. The fixed bit is copying the head when it's not the removee.
Of course there's another base case: if the list is empty, the removee can't be found. That's an error.
Putting this in code:
MyList removeNumber(MyList m, int removee) {
if (m == null) throw new RuntimeException("removee not found");
if (m.value == removee) return m.next;
return new MyList(m.value, removeNumber(m.next, removee));
}
Putting the function to use would look something like this:
MyList originalList = ... // list of 1 to 5.
MyList newListWith3removed = removeNumber(originalList, 3);
System.out.println("Original list:");
for (MyList p : originalList) System.out.println(p.value);
System.out.println("With 3 removed:");
for (MyList p : newListWith3removed) System.out.println(p.value);
The output will look as expected: 1 to 5 in the first list and 1,2,4,5 in the second. I.e. the first list is unchanged.
//This function will always return a new list with 'remove' removed
MyList removeNumber(MyList m, int remove){
//if m is empty List, return an empty list
//if head is not the int to remove, return a New list from
// head concat removeNumber(m.next,remove)
//else return removeNumber(m.next,remove)
}
I think it lacks information. I'm assuming however a very traditional implementation for linked list, for instance:
class MyList {
MyList prev;
MyList next;
int data;
static MyList removeNumber(MyList m,int removee) {
if(m == null) return null; // already empty
if(m.data == removee) { // m already is the node to throw away
if(m.prev != null)// relink
m.prev.next = m.next;
if(m.next != null)// relink
m.next.prev = m.prev;
return m.prev;
}
// if this node isn't the one yet, keep looking for
return removeNumber(m.next,removee);
}
}
There are plenty different ways to do that, but you have to provide more info in order to allow us to point you the correct literature.

Will adding a Node recursively work in any position of a Singly Linked List?

I learned that to add a Node to the front of the Singly Linked List the code is
head = new Node(data,head);
I am confused behind the logic for if this will work for instance, in some random index in the middle of the list. I tried implementing the code:
public void add(int index, int data) {
if(index == 0) {
head = new Node(data,head);
} else {
for(int pos = 0; pos < size; pos++) {
if(pos == index) {
//Add it//
head = new Node(data,head);
size++;
} else {
//Go to the next Node//
head = head.getNext();
}
}
}
}
}
I'm still kind of confused on this logic, because I feel like this will cause the linked list after the adding has completed to lose it's data. So if I add in index 5 for example, then 6, 7,8,9, etc. will no longer be a part of the linked list.
You should be more clear on how a Singly Linked List works. I would suggest you go through some good article or a video tutorial. And what you are doing here is iteration, not recursion.
A head is pointer/reference to a node that is at the starting of the Linked List.
So, when does a head change?
When you insert a new node at the 0th (assuming you are starting from 0) or when you delete the first node.
In every other case, the head remains the same. Adding to the front of the Linked List would be same as adding a newNode where index=0. The logic to add a newNode at any index should be same. However, in case of adding to the 0th index, you should reset your head to the newNode.
Your code seems to be flawed. Take an input and try to go step by step. It might help you to pin down the flaw, if any. Cheers.
To add a node to the beginning of your linked list that line will work, assuming you have something like this in your constructor:
setNext(head);
This way you don't lose track of your list. If you simply reset your head without setting up the reference to the rest of the list you will lose it.
However your index 5 example doesn't apply here. In that case you're inserting a node into the middle of your linked list, not at the beginning, so the process would be different. For example, if you wanted to insert something in position 5 you would have to set the next of the node in position 4 to your new node and the next of your new node to the node currently in position 5. See this for a more detailed explanation: http://www.mycstutorials.com/articles/data_structures/linkedlists

Convert Java Code to Objective-C Code?

Can any one help me converting the following Java Code into Objective-C Code. I knew Objective-C but I am not able to translate this code into objective-C.
This is Java Code.
public MyList RecReverse() { //my attempt at the recursive method
if (head.getNext() == null) {
return this;
}
MyList remainder = new MyList();
remainder.head = head.getNext(); // New list has rest of this list (after head)
ListNode temp = new ListNode(head.getString()); // save the first thing in list
remainder = remainder.RecReverse(); //reverse the things in the new 2nd part list
remainder.end().setNext(temp); // put old head on the end
return remainder;
}
private ListNode end() {
ListNode curr = head;
while (curr.getNext() != null) {
curr = curr.getNext();
}
return curr;
}
Thanks
The code is a poor algorithm for reversing a linked list. You presumably have either converted the rest of the class, or have your own linked list class and are just trying to copy the reversal algorithm. You should really include these details and what you've tried when you ask questions on SO, without them people answering can often only guess and you've failed to show any effort - the latter is important.
While this code strongly suggests a linked list there is no clue in this fragment whether this is a single or double-linked list. The code fragment you supply indicates that you have a MyList class with manages a linked list made up of ListNode objects.
The basic operations on a linked list are typically:
Access/change the value stored in the current node - in your code this is the property head and it is an object reference of type ListNode; which itself appears to hold a string.
Access/change the reference to the remainder ("tail") of the list - in your code the getNext & setNext methods.
The method you show RecReverse is a way to recursively produce a new list which is the reverse of the current list. The algorithm does this by reversing the tail of the list and then appending the head onto the end - using the method end.
If the list is double-linked and/or keeps a reference to the end of the list then the algorithm is ok - the method end does not need to traverse the list in this case. Just write it in Objective-C and add it to your list class.
If the list is single-linked and does not keep a reference to the end of the list then the algorithm is poor and the method end does need to traverse the list. This makes it an O(n^2) algorithm - every step traverses the list.
A better algorithm in this case is to use an accumulating parameter. In pseudo-code this is:
Reverse(l)
if length(l) <= 1
then return l // empty list or list with one element reversed is itself
else return ReverseHelper(l, new empty list)
ReverseHelp(remainder, result)
if remainder is empty
then return result // no more elements left to process
else return ReverseHelp(tail of remainder, add head of remainder to front of result)
Implement that on Objective-C and add it to your linked list class.
HTH
You haven't really given context to what 'MyList' objects are.
But if you are simply attempting to reverse an array using any method possibly you can use the following single line:
NSArray* reversedArray = [[array reverseObjectEnumerator] allObjects];

Categories