Microsoft Interview Question
Software Engineer in TestsCountry: United States
Its simple problem if you can you know how to find whether a list have loop or not.
Algorithm :- Take two pointers p1 and p2. Start both from head. Loop until p1 and p2 meet again. But p1 will incre one step i.e. p1 = p1-> next and p2 will two steps i.e. p2= p2->next->next.Once they meet. Do following step.
Now make p1=head and start increment one step by one for both p1 and p2. When they meet again will be the starting point of the cycle.
I thought the way you're thinking here... but every element has its next pointer and then returning the same element.
So, I am thinking that every element is starting element in circular linked lists.
My code, check Linkedlist has cycle and return entry node of cycle:
public static LinkedListNode find_cycle_entry(LinkedListNode head){
if(head==null){
System.out.println("err, no cycle!");
return null;
}
LinkedListNode slow=head.next;
if(slow==null){
System.out.println("err, no cycle!");
return null;
}
LinkedListNode fast=head.next.next;
if(fast==null){
System.out.println("err, no cycle!");
return null;
}
while(fast!=null){
if(slow==fast){
break;
}
slow=slow.next;
fast=fast.next;
if(fast==null){
System.out.println("err, no cycle!");
return null;
}
fast=fast.next;
}
if(fast==null){
System.out.println("err, no cycle!");
return null;
}
slow=head;
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}
return slow;
}
How you are returning the Node from where cycle is starting. Can you write down steps in seperate lines?
firstly, slow node moves one time one step, fast node moves one time two steps.
there is a loop, So when slow encounter fast, slow go back to head and move one time one step.
Now, fast move one time one step too.
when they meet again, the node is entry.
Given two iters A,B, such that A is always ahead of B. If both A,B are in a circle, then going forward from A, it should be possible to reach B. Since we don't know ahead of time how many steps it will take to reach B, let's accelerate after each iteration, i.e. step++; otherwise, if step is constant, it may take many more iterations before A overtakes B...
static Node findStart(final Node[] list) {
int step = 1;
if (list.length <= 2) {
return list[0];
}
Node headconstant = list[0];
Node headaccel = list[2];
boolean isLoop = false;
while ((headaccel != null) && !isLoop) {
for (int i = 1; i <= step; i++) {
headaccel = headaccel.next;
if (headaccel==headconstant) {
isLoop = true;
break;
} else if (headaccel == null) {
break;
}
}
headconstant = headconstant.next;
step++;
}
return headaccel;
}
One problem with the above code, though it finds a loop, it doesn't always specify where the cycle starts. In this case, you'd need additional info. Add a visitors integer K such that, if headaccel visits a node N, it sets K to 1. headaccel is only needed with a step of 1 . If headaccel visits N again, increment K to 2. If K=2, then you've detected a loop, and the start of the cycle.
I guess not....
The problem with this solution is ensuring that "seen" is marked as false for all the nodes before you start. If the linked list has a loop, it isn't possible to iterate over each node to set "seen" to "false" as an initial value for each node. It might be possible to overcome some of this by using a big integer rather than a boolean and using a random integer as your marker. In that case there is is a good chance that no node will have your inital value, but a small chance that one would and your algorithm would fail.
Even if you are able to solve the initial value problem, each node in a linked list may not have a field to use for this purpose. Requiring such a field in each node would mean that this is not a generic solution. As we will see later, this field is not needed for a perfectly correct and efficient solution anyway.
Can we just traverse the list from head and each time check if the node is visited? We can have something like this in the Node class
public void setVisited() {
visited = true;
}
public boolean getVisited() {
return visited;
}
then we can have a method that traverse the list that returns the first node that's visited twice
public Node traverse(LinkedList<Integer> list) {
for (Iterator<Integer> it = list.iterator(); list.hasNext();) {
if (it.next().getVisited()) {
return it.next();
} else {
it.next().setVisited();
}
}
return null;
}
I guess not....
The problem with this solution is ensuring that "seen" is marked as false for all the nodes before you start. If the linked list has a loop, it isn't possible to iterate over each node to set "seen" to "false" as an initial value for each node. It might be possible to overcome some of this by using a big integer rather than a boolean and using a random integer as your marker. In that case there is is a good chance that no node will have your inital value, but a small chance that one would and your algorithm would fail.
Even if you are able to solve the initial value problem, each node in a linked list may not have a field to use for this purpose. Requiring such a field in each node would mean that this is not a generic solution. As we will see later, this field is not needed for a perfectly correct and efficient solution anyway.
No need for slow/fast pointers. Problem definition is using characters, so:
Node* cycle_start_node(Node* n) {
bool seen[256];
memset(seen, false, 256*sizeof(bool));
while (n != NULL) {
if (seen[n->val]) return n;
seen[n->val] = true;
n = n->next;
}
return NULL;
}
umairsaeed.com/2011/06/23/finding-the-start-of-a-loop-in-a-circular-linked-list/
- h4ck4r August 16, 2012