I need to return the head of the linked list with all the duplicate elements deleted. I understand the logic of the problem, but I am getting confused in using recursion.
/*
Node is defined as
class Node {
int data;
Node next;
}
*/
Node RemoveDuplicates(Node head) {
if ((head == null) || (head.next == null))
return head;
else {
RemoveDuplicates(head.next);
if (head.data==head.next.data) head.next = head.next.next;
}
return head;
}
If I call the function RemoveDuplicates(head.next) before the if condition; it works fine. However if I swap the order of the statements (rest everything is exactly the same)like:
if (head.data==head.next.data) head.next = head.next.next;
RemoveDuplicates(head.next);
the code is unable to correctly solve for a test case like '1->1->1->1'. The output I get in the latter case is '1->1'.
I would really like some suggestions on how I could understand recursion better.
Firstly, your code does only solve if the list is in order, it cannot remove all duplicated node if data in random position, ex: 1, 2, 3, 1, 1, 2, 3
Secondly, for your concern, you can think it like below:
Case 1:
RemoveDuplicates(head.next);
if (head.data==head.next.data) head.next = head.next.next;
You check from element right before the end of the list, compare its data and the next data, if matched, replace the next node by the next next node. Then, jump to the previous node and repeat.
Case 2:
if (head.data==head.next.data) head.next = head.next.next;
RemoveDuplicates(head.next);
You begin with the first node, check if it duplicate with the next node. If duplicated, bring the 3th node to replace the 2nd node. The, jump to the next node (now is the original 3rd node) to check if it duplicate to the next node. You see, you miss checking the 1st node and the original 3rd node.
I think you should try mode debug to understand deeply about this.
BTW, try to apply convention to your code. J
Hope this help!
The problem is that you "skip" some nodes in the latter case.
Let's name the nodes in your example to see what's happening:
v
1 -> 1 -> 1 -> 1
a b c d
v indicates the current reference of head in your method.
If you now do a check first, you compare a and b, then remove b:
v
1 -> 1 -> 1
a c d
Then you do a recursion step, which travels forward one node to c:
The problem is that you "skip" some nodes in the latter case.
Let's name the nodes in your example to see what's happening:
v
1 -> 1 -> 1 -> 1
a b c d
v indicates the current reference of head in your method.
If you now do a check first, you compare a and b, then remove b:
v
1 -> 1 -> 1
a c d
And here's your problem. You never compared c to a value to its left, i.e. a/c or b/c.
This problem doesn't occur when switching the lines because that way you're walking the other way, i.e. you go through your list bottom-up (right to left) and only compare/delete to the right ("behind you" in walking direction).
Related
How can I write a function in java that reverse a singly linked list by dividing it into half that means (n/2) nodes for first part and rest is second Part (n is size of the liked list) until it reaches one Node and then merge this divided parts. Using two new Linked list is allowed in each divide but using list Node is not. The function must be void and there are no parameters for the function. I have n, head and tail of main Linked list.
I found this code on websites but it doesn't divide Linked list into half, so it is not helpful.
static ListNode reverseR(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode first = head;
ListNode rest = head.next;
// reverse the rest of the list recursively
head = reverseR(rest);
// fix the first node after recursion
first.next.next = first;
first.next = null;
return head;
}
Because you're working with a linked list, the approach you suggest is unlikely to be efficient. Ascertaining where the midpoint lies is a linear time operation, and even if the size of the list was known, you would still have to iterate up to the midpoint. Because you have a linear term at each node of the recurrence tree, the overall performance will be O(n lg n), slower than the O(n) bound for the code which you have provided.
That being said, you could still reverse the list by the following strategy:
Step 1: Split the list L into A (the first half) and B (the second half).
Step 2: Recurse on each of A and B. This recursion should bottom out
when given a list of length 1.
Step 3: Attach the new head of the reversed A to the new tail of the reversed B.
You can see that to begin with, our list is AB. We then recurse to get A' and B', each the reversed version of the half lists. We then output our new reversed list B'A'. The first element of the original A is now the last element of the list overall, and the last element of the original B is now the first overall.
Problem Statement: Given a circular linked list, implement an algoirthm that returns the node at the beginning of the loop.
The answer key gives a more complicated solution than what I propose. What's wrong with mine?:
public static Node loopDetection(Node n1) {
ArrayList<Node> nodeStorage = new ArrayList<Node>();
while (n1.next != null) {
nodeStorage.add(n1);
if (nodeStorage.contains(n1.next)) {
return n1;
}
else {
n1 = n1.next;
}
}
return null;
}
Your solution isO(n^2) time (each contains() in ArrayList is O(n) time) and O(n) space (for storing nodeStorage), while the "more complicated" solution is O(n) time and O(1) space.
The book offers the following solution, to whomever is interested, which is O(n) time and O(1) space:
If we move two pointers, one with speed 1 and another with speed 2,
they will end up meeting if the linked list has a loop. Why? Think
about two cars driving on a track—the faster car will always pass the
slower one! The tricky part here is finding the start of the loop.
Imagine, as an analogy, two people racing around a track, one running
twice as fast as the other. If they start off at the same place, when
will they next meet? They will next meet at the start of the next lap.
Now, let’s suppose Fast Runner had a head start of k meters on an n
step lap. When will they next meet? They will meet k meters before the
start of the next lap. (Why? Fast Runner would have made k + 2(n - k)
steps, including its head start, and Slow Runner would have made n - k
steps. Both will be k steps before the start of the loop.) Now, going
back to the problem, when Fast Runner (n2) and Slow Runner (n1) are
moving around our circular linked list, n2 will have a head start on
the loop when n1 enters. Specifically, it will have a head start of k,
where k is the number of nodes before the loop. Since n2 has a head
start of k nodes, n1 and n2 will meet k nodes before the start of the
loop. So, we now know the following:
1. Head is k nodes from LoopStart (by definition).
2. MeetingPoint for n1 and n2 is k nodes from LoopStart (as shown above). Thus, if we move n1 back to Head and keep n2 at MeetingPoint,
and move them both at the same pace, they will meet at LoopStart.
LinkedListNode FindBeginning(LinkedListNode head) {
LinkedListNode n1 = head;
LinkedListNode n2 = head;
// Find meeting point
while (n2.next != null) {
n1 = n1.next;
n2 = n2.next.next;
if (n1 == n2) {
break;
}
}
// Error check - there is no meeting point, and therefore no loop
if (n2.next == null) {
return null;
}
/* Move n1 to Head. Keep n2 at Meeting Point. Each are k steps
/* from the Loop Start. If they move at the same pace, they must
* meet at Loop Start. */
n1 = head;
while (n1 != n2) {
n1 = n1.next;
n2 = n2.next;
}
// Now n2 points to the start of the loop.
return n2;
}
I had trouble visualizing what was going on with this algorithm. Hopefully this helps someone else.
At time t = k(3), p2 is twice the distance from the head(0) as p1, so for them to get back in line, we need p2 to 'catch up' to p1 and it will take L - k(8) 5 more steps to occur. p2 is travelling at 2x the speed of p1.
At time t = k + (L - k) (8), p2 needs to travel k steps forward to get back to k. If we reset p1 back to the head(0), we know that p1 and p2 will both meet back at k(3, 19 respectively) if p2 is travelling at the same speed as p1.
There is the solution given by amit. The problem is that you either know it or you don't, but you won't be able to figure it out in an interview. Since I have never had a need to find a cycle in a linked list, knowing it to me is pointless except for passing interviews. So for an interviewer, stating this as an interview question, and expecting amir's answer (which is nice because it has linear time and zero extra space), is quite stupid.
So your solution is mostly fine, except that you should use a hash table, and you must make sure that the hash table hashes references to nodes and not nodes. Say you have a node containing a string and a "next" pointer, and the hash function hashes the string and compares nodes as equal if the strings are equal. In that case you'd find the first node with a duplicate string, and not the node at the start of the loop, unless you are careful.
(amir's solution has a very similar problem in languages where == compares the objects, and not the references. For example in Swift, you'd have to use === (compares references) and not == (compares objects)).
In an interview, i was given a function:
f(n)= square(f(n-1)) - square(f(n-2)); for n>2
f(1) = 1;
f(2) = 2;
Here n is the level of an n-array tree. f(n)=1,2,3,5,16...
For every level n of a given N-Array I have to print the f(n) node at every level. For example:
At level 1 print node number 1 (i.e. root)
At level 2 print node number 2 (from left)
At level 3 print node number 3 (from left)
At level 4 print node number 5... and so on
If the number of nodes(say nl) at any level n is less than f(n), then have to print node number nl%f(n) counting from the left.
I did a basic level order traversal using a queue, but I was stuck at how to count nodes at every level and handle the condition when number of nodes at any level n is less than f(n).
Suggest a way to proceed for remaining part of problem.
You need to perform Level Order Traversal.
In the code below I am assuming two methods:
One is getFn(int level) which takes in an int and returns the f(n) value;
Another is printNth(int i, Node n) that takes in an int and Node and beautifully prints that "{n} is the desired one for level {i}".
The code is simple to implement now. Comments explain it like a story...
public void printNth throws IllegalArgumentException (Node root) {
if (root == null) throw new IllegalArgumentException("Null root provided");
//Beginning at level 1 - adding the root. Assumed that levels start from 1
LinkedList<Node> parent = new LinkedList<>();
parent.add(root)
int level = 1;
printNth(getFn(level), root);
//Now beginning from the first set of parents, i.e. the root itself,
//we dump all the children from left to right in another list.
while (parent.size() > 0) { //Last level will have no children. Loop will break there.
//Starting with a list to store the children
LinkedList<Node> children = new LinkedList<>();
//For each parent node add both children, left to right
for (Node n: parent) {
if (n.left != null) children.add(n.left);
if (n.right != null) children.add(n.right);
}
//Now get the value of f(n) for this level
level++;
int f_n = getFn(level);
//Now, if there are not sufficient elements in the list, print the list size
//because children.size()%f(n) will be children.size() only!
if (children.size() < f_n) System.out.println(children.size());
else printNth(level, children.get(f_n - 1)); //f_n - 1 because index starts from 0
//Finally, the children list of this level will serve as the new parent list
//for the level below.
parent = children;
}
}
Added solution here
I have used queue to read all nodes at a particular level, before reading the nodes checking if given level(n) is equal to current level then checking size of the queue is greater than f(n) then just read f(n) nodes from queue and mark it as deleted otherwise perform mod operation and delete the node nl%f(n).
I have been trying to get this to work but while it works for majority of the input sometimes it gives the wrong output. I have spent some time debugging the code and it seems the problem is when i get a Node that is smaller than the root but bigger than the left node under the root.
How can I traverse the right sub-tree and still return the right key if no node in the right sub-tree is the floor node for that key?
Recall that if you do anything recursively, it can be transformed* into iteration.
Let's consider taking the floor of a well-formed BST, which should simply be the smallest element which is less than or equal to your key in the tree. All we have to do is traverse the tree to get it.
Let's implement it recursively so we can tease out a few important corollaries between iteration and recursion.
// Assuming non-null root node with method declaration
private Node floor(Node root, Key key, Node lowestNode) {
if(key.compareTo(root.getKey()) <= 0) {
if(root.getLeft() != null) {
return floor(root.getLeft(), key, lowestNode);
} else {
return root.compareTo(lowestNode) < 0 ? root : lowestNode;
}
} else {
if(root.getRight() != null) {
lowestRightNode.add(root);
return floor(root.getRight(), key, lowestNode);
} else {
return lowestNode;
}
}
Let's walk through the conditions for success.
If we compare a node to be less than or equal to our key value:
If we have a left child, there's something smaller. Traverse down the left half of the tree.
Otherwise, we're at the floor - which means we're at the node whose value is less than or equal to our key. Return it.
Otherwise (our node has a value greater than our key):
If we have a right child, there's a chance that our work isn't done yet (something's smaller). We'd like to keep it around since we could step off of the tree, so let's store it, then traverse down the right half of the tree.
Otherwise, we've fallen off of the tree. Return the smallest element we've kept track of.
An example may look something like this:
9
/ \
3 14
/ \
1 2
With a key of 12:
Compare with 9. We're larger. Store 9 in our lowest node variable, recurse right.
Compare with 14. We're smaller, but we don't have a left child. We compare the value 14 to 9 and 9 is smaller, so we return the node with 9.
If we want to convert this into iteration, then think about your starting point, your conditional check, and your incrementation steps.
Starting point: A non-null node
Conditional check:
key.compareTo(root.getKey()) <= 0
root.getLeft() != null
continue
root.compareTo(lowestRightNode) < 0 ? root : lowestRightNode
terminal
else
root.getRight() != null
store temp value and continue
return lowestRightNode
terminal
Pay close attention to your continuation conditions, and what other work you'd have to do to keep track of the lowest node you've seen so far (only for the right-hand side, that is).
*: Some recursive operations are more painful to convert than others, of course.
If you are provided the head of a linked list, and are asked to reverse every k sequence of nodes, how might this be done in Java? e.g., a->b->c->d->e->f->g->h with k = 3 would be c->b->a->f->e->d->h->g->f
Any general help or even pseudocode would be greatly appreciated! Thanks!
If k is expected to be reasonably small, I would just go for the simplest thing: ignore the fact that it's a linked list at all, and treat each subsequence as just an array-type thing of things to be reversed.
So, if your linked list's node class is a Node<T>, create a Node<?>[] of size k. For each segment, load k Nodes into the array list, then just reverse their elements with a simple for loop. In pseudocode:
// reverse the elements within the k nodes
for i from 0 to k/2:
nodeI = segment[i]
nodeE = segment[segment.length-i-1]
tmp = nodeI.elem
nodeI.elem = nodeE.elem
nodeE.elem = tmp
Pros: very simple, O(N) performance, takes advantage of an easily recognizable reversing algorithm.
Cons: requires a k-sized array (just once, since you can reuse it per segment)
Also note that this means that each Node doesn't move in the list, only the objects the Node holds. This means that each Node will end up holding a different item than it held before. This could be fine or not, depending on your needs.
This is pretty high-level, but I think it'll give some guidance.
I'd have a helper method like void swap3(Node first, Node last) that take three elements at an arbitrary position of the list and reverses them. This shouldn't be hard, and could could be done recursively (swap the outer elements, recurse on the inner elements until the size of the list is 0 or 1). Now that I think of it, you could generalize this into swapK() easily if you're using recursion.
Once that is done, then you can just walk along your linked list and call swapK() every k nodes. If the size of the list isn't divisble by k, you could either just not swap that last bit, or reverse the last length%k nodes using your swapping technique.
TIME O(n); SPACE O(1)
A usual requirement of list reversal is that you do it in O(n) time and O(1) space. This eliminates recursion or stack or temporary array (what if K==n?), etc.
Hence the challenge here is to modify an in-place reversal algorithm to account for the K factor. Instead of K I use dist for distance.
Here is a simple in-place reversal algorithm: Use three pointers to walk the list in place: b to point to the head of the new list; c to point to the moving head of the unprocessed list; a to facilitate swapping between b and c.
A->B->C->D->E->F->G->H->I->J->L //original
A<-B<-C<-D E->F->G->H->I->J->L //during processing
^ ^
| |
b c
`a` is the variable that allow us to move `b` and `c` without losing either of
the lists.
Node simpleReverse(Node n){//n is head
if(null == n || null == n.next)
return n;
Node a=n, b=a.next, c=b.next;
a.next=null; b.next=a;
while(null != c){
a=c;
c=c.next;
a.next=b;
b=a;
}
return b;
}
To convert the simpleReverse algorithm to a chunkReverse algorithm, do following:
1] After reversing the first chunk, set head to b; head is the permanent head of the resulting list.
2] for all the other chunks, set tail.next to b; recall that b is the head of the chunk just processed.
some other details:
3] If the list has one or fewer nodes or the dist is 1 or less, then return the list without processing.
4] use a counter cnt to track when dist consecutive nodes have been reversed.
5] use variable tail to track the tail of the chunk just processed and tmp to track the tail of the chunk being processed.
6] notice that before a chunk is processed, it's head, which is bound to become its tail, is the first node you encounter: so, set it to tmp, which is a temporary tail.
public Node reverse(Node n, int dist) {
if(dist<=1 || null == n || null == n.right)
return n;
Node tail=n, head=null, tmp=null;
while(true) {
Node a=n, b=a.right; n=b.right;
a.right=null; b.right=a;
int cnt=2;
while(null != n && cnt < dist) {
a=n; n=n.right; a.right=b; b=a;
cnt++;
}
if(null == head) head = b;
else {
tail.right=b;tail=tmp;
}
tmp=n;
if(null == n) return head;
if(null == n.right) {
tail.right=n;
return head;
}
}//true
}
E.g. by Common Lisp
(defun rev-k (k sq)
(if (<= (length sq) k)
(reverse sq)
(concatenate 'list (reverse (subseq sq 0 k)) (rev-k k (subseq sq k)))))
other way
E.g. by F# use Stack
open System.Collections.Generic
let rev_k k (list:'T list) =
seq {
let stack = new Stack<'T>()
for x in list do
stack.Push(x)
if stack.Count = k then
while stack.Count > 0 do
yield stack.Pop()
while stack.Count > 0 do
yield stack.Pop()
}
|> Seq.toList
Use a stack and recursively remove k items from the list, push them to the stack then pop them and add them in place. Not sure if it's the best solution, but stacks offer a proper way of inverting things. Notice that this also works if instead of a list you had a queue.
Simply dequeue k items, push them to the stack, pop them from the stack and enqueue them :)
This implementation uses ListIterator class:
LinkedList<T> list;
//Inside the method after the method's parameters check
ListIterator<T> it = (ListIterator<T>) list.iterator();
ListIterator<T> reverseIt = (ListIterator<T>) list.listIterator(k);
for(int i = 0; i< (int) k/2; i++ )
{
T element = it.next();
it.set(reverseIt.previous());
reverseIt.set(element);
}