Data structure for fast retrieval of middle element - algorithm

I need to solve a problem where I can insert left and right. And then extract from the data in the middle of the array.
I already tried to solve this with using linkedlist. However this approach was too slow to be accepted as an solution.
What data structure would you suggest I use if i need fast insertion at the beginning and the end of a list as well as fast retrieval of the middle element?
Here is the code I've already tried with:
private static void middleQueue(int loopLength, String[] commandsArray) {
LinkedList<String> linkedList = new LinkedList<>();
int counterSize = 0;
for (int i = 0; i < commandsArray.length; i++) {
if(commandsArray[i].equals("R")){
linkedList.add(commandsArray[i+1]);
i++;
counterSize++;
}
else if(commandsArray[i].equals("L")){
linkedList.addFirst(commandsArray[i+1]);
i++;
counterSize++;
}
else if(commandsArray[i].equals("E")){
if((linkedList.size() & 1) == 0)
System.out.println(linkedList.remove((counterSize / 2)-1));
else
System.out.println(linkedList.remove((counterSize / 2)));
counterSize--;
}
}
}

Take 3 pointers first, middle, last pointer.
Then there are 2 cases:
if you add from first
ans. You need to shift the middle pointer to left side then its current position.
if you add from last
ans. You just need increase the middle pointer to its next.

As others have pointed out, you need a data structure with 3 pointers.
A doubly linked list will be good. But , if you will use a singly list list (with pointers only in one direction), then you will either be able to only move right or left (not both at the same time). SLL wont serve the purpose.
See this for the implementation of a very similar problem: https://www.geeksforgeeks.org/design-a-stack-with-find-middle-operation/

In Java, you should use two ArrayDeques, one for the first half of the the list and one for the last half. Move elements from one to the other to keep them the same size, so you always have access to the middle.
This will be faster and more memory-efficient than using LinkedList.

Related

i had an interview and they ask me and i didn't know the answer i get a answer

The question is write a pseudo code that returns true if a given one way linked list reads the same in both directions and false otherwise. In addition we know the size of the list stored in a variable n. The expected solution should have computational complexity O(n) and memory complexity O(1).
example : 1->2->3->3->2->1 return true
example : 1->2->3->1->2->3 return false
It is possible to reverse a one way linked list, doing a single pass(see the end of this answer). The restriction on the additional memory is quite constraining in this task, so the best approach I figured is a bit hacky.
Iterate over the list and reverse the part that comes after its center(namely after position n/2) using the algorithm I mentioned above. Save a pointer to the last element in the list - you'll need it for step 2.
Simultaneously iterate over the list from the beginning to position n/2 and the reversed portion(from n to n/2). The elements that you iterate over in both portions should match. For this you need two variables - one iterating over the first portion and one for the second(and one to remember how many elements you've already processed).
Reverse back the second half of the list so that the list is not changed at the end.
Overall I meet the requirements of the task.
The algorithm to reverse a one-way linked list goes like this(using c++ as example):
struct node {
node* next;
int data;
};
// reverses a one-way list and returns pointer to the new list head
node* reverse(node* c) {
node* prev = NULL;
node* cur = c;
// I assume the list is NULL terminated;
while (cur) {
node* temp = cur->next;
cur->next = prev;
prev = cur;
cur = temp;
}
return prev;
}

Where did I go wrong in simplifying this code fragment of reversing a singly linked list?

I found a solution on the CareerCup for reversing a singly linked list:
void reverse(node n, node prev)
{
if (n == null) { head = prev; return; }
reverse(n.next, n);
n.next = prev;
}
call reverse (head, null);
Which is good to understand and study.If the original list is "1->2->3->4->5", the reversed output will be "5->4->3->2->1".
I am trying to simplifying this solution a bit by using only one parameter, which is the current Node where are working on:
void reverse2(Node n)
{
if(n.next==null){ head = n;return; }
reverse2(n.next);
n=n.next.next;
}
call reverse2(head)
Maybe you may already tell, the result is not correct, after the method finishes, the modified remains "1->2->3->4->5".
I was confused at first, after thought for a while, I think my fault is as this line:
n=n.next.next;
in which I was planning to make the next node point back to current node, however, in my current recursion, I am working on the node "n" it self, I wasn't changing anything of this current node n, thus the resulting list is not changed at all.
I am not 100% convinced by myself, could experts offer some guidance? Thanks.
The problem with you algorithm is that it changes nothing in the original data structure.
The original algorithm did this:
n.next = prev;
which actually reversed one node. You only call:
n.next = prev;
Which simply changes a parameter of the method, but does nothing else.
I doubt you could solve this problem with a recursion method that takes only one parameter, because after modifying the current node N(i) you need to move on to the next node N(i+1), and that next node should be made to point to N(i). So the next call should know both about N(i) and N(i+1).
First thought,
n=n.next.next; why are you changing the entire node as such??
To reverse the linked list isn't it only required to change the next attribute?
It should have been something like
n.next.next = n
consider when n points to 4 in 1->2->3->4->5
now we have 4.next = 5 and 5.next = null initially
on excecution it would be like
4.next.next => 5.next = 4
1->2->3->4->5---
^------|

How to check if a circular single linked list is pallindrome or not?

Question: I have a single linked list (i.e. a list with only pointer to the next node). Additionally this is a circular linked list (in this example, the last node has a pointer to the first node). Every node in the list contains a char.
An example of such a list can be: a->b->c->b->a
Now how can I verify if this list is a pallindrome?
I have thought of the following solution:
Start from the head of list. Find the length of the list and then the mid node. Now start again from the head of the list and keep pushing elements in stack until the mid. Now traverse the list from the mid and pop element. If the value of the popped element is equal to the value of the current node. if not, return false. otherwise, continue until the stack is empty and we've verified all chars. CONS: uses extra stack space :(
Start from the head of list. Find the length of the list and then the mid node. now reverse the 2nd half of this list. and then using 2 pointers (one pointing to start and the other pointing to the mid+1'th element), check if the values are same. if not, return false. else continue until we reach the start node again. CONS: Changing original data structure.
Is there a more elegant way to approach this problem (which hopefully does not use O(n) extra space or changes original list)? I'm interested in the algorithm rather than any specific implementation.
Thanks
Since you're dealing with a single linked list, you must use a little extra space or a lot more extra time.
Your first approach sounds reasonable, but you can determine the length of the list and palindrome-ness in a single run.
We modify the so-called Floyd's Cycle-Finding Algorithm:
two pointers, "slow" and "fast", both start at the list head; the slow pointer advances one list element per iteration, the fast pointer two elements
in each step, the slow pointer pushes the current element on the stack
if the fast pointer reaches the end of the list, the slow pointer points to the middle of the list, so now:
the slow pointer advances to the end of the list, and in each step:
it pops one element from the stack and compares it to the current list element (if they are not equal, return false)
if the slow pointer reaches the end of the list, it is a palindrome
A little extra work is required for lists with an odd number of elements.
This is in pseudo-Haskell (I can't remember the exact syntax these days) and I've written for the non-circular case -- to fix that, just replace the clause matching against [] with whatever condition you use to identify you've come full circle.
p(xs) = q(xs, Just(xs)) != Nothing
q([], maybeYs) = maybeYs
q(x : xs, Nothing) = Nothing
q(x : xs, maybeYs) =
let maybeZs = q(xs, maybeYs) in
case maybeZs of
Nothing -> Nothing
Just (x :: zs) -> Just(zs)
otherwise -> Nothing
Since you know the Linked List does make a cycle, and you are only looking for palindromes starting at head, you can make this easier on yourself.
A -> B -> C -> B -> A
In this case, start with a pointer at head (call it H), and a pointer at head.Left() (call it T).
Now keep moving the head pointer H to the right, and the tail pointer T to the left.
As you walk the list, verify that the values of those elements are equal (i.e. a palindrome).
Your stopping condition however take a bit more. There are two cases:
Both pointers end point at the same element (i.e. odd number of elements)
The H pointer is pointing at the element just to the right of T.
So, you stop if H==T or if H==(T.Right()).
Using this approach (or similar) you visit each element just once.
Use the Tortoise and Hare approach as in the other solutions if you don't know if the linked list is cyclic.
Just paste my implementation so we could compare with each others, full test here:
/**
* Given a circular single linked list and the start pointer, check if it is a palindrome
* use a slow/fast pointer + stack is an elegant way
* tip: wheneve there is a circular linked list, think about using slow/fast pointer
*/
#include <iostream>
#include <stack>
using namespace std;
struct Node
{
char c;
Node* next;
Node(char c) {this->c = c;}
Node* chainNode(char c)
{
Node* p = new Node(c);
p->next = NULL;
this->next = p;
return p;
}
};
bool isPalindrome(Node* pStart)
{
Node* pSlow = pStart;
Node* pFast = pStart;
stack<Node*> s;
bool bEven = false;
while(true)
{
// BUG1: check fast pointer first
pFast = pFast->next;
if(pFast == pStart)
{
bEven = false;
break;
}
else
{
pFast = pFast->next;
if(pFast == pStart)
{
bEven = true;
break;
}
}
pSlow = pSlow->next;
s.push(pSlow);
}
if(s.empty()) return true; // BUG2: a, a->b->a
if(bEven) pSlow = pSlow->next; // BUG3: a->b->c->b->a, a->b->c->d->c->b->a: jump over the center pointer
while(!s.empty())
{
// pop stack and advance linked list
Node* topNode = s.top();
s.pop();
pSlow = pSlow->next;
// check
if(topNode->c != pSlow->c)
{
return false;
}
else
{
if(s.empty()) return true;
}
}
return false;
}
I think we dont need an extra space for this. And this can be done with O(n) complexity.
Modifying Philip's solution:
We modify the so-called Floyd's Cycle-Finding Algorithm:
Two pointers, "slow" and "fast", both start at the list head; the slow pointer advances one list element per iteration, the fast pointer two elements
in each step, the slow pointer pushes the current element on the stack
if the fast pointer reaches the end of the list, the slow pointer points to the middle of the list, so now:
Have another pointer at the start of the linked-list (start pointre) and now -
move the start pointer and the slow pointer one by one and compare them - if they are not equal, return false
- if the slow pointer reaches the end of the list, it is a palindrome
This is O(n) time complexity and no extra space is required.

Check if two linked lists merge. If so, where?

This question may be old, but I couldn't think of an answer.
Say, there are two lists of different lengths, merging at a point; how do we know where the merging point is?
Conditions:
We don't know the length
We should parse each list only once.
The following is by far the greatest of all I have seen - O(N), no counters. I got it during an interview to a candidate S.N. at VisionMap.
Make an interating pointer like this: it goes forward every time till the end, and then jumps to the beginning of the opposite list, and so on.
Create two of these, pointing to two heads.
Advance each of the pointers by 1 every time, until they meet. This will happen after either one or two passes.
I still use this question in the interviews - but to see how long it takes someone to understand why this solution works.
Pavel's answer requires modification of the lists as well as iterating each list twice.
Here's a solution that only requires iterating each list twice (the first time to calculate their length; if the length is given you only need to iterate once).
The idea is to ignore the starting entries of the longer list (merge point can't be there), so that the two pointers are an equal distance from the end of the list. Then move them forwards until they merge.
lenA = count(listA) //iterates list A
lenB = count(listB) //iterates list B
ptrA = listA
ptrB = listB
//now we adjust either ptrA or ptrB so that they are equally far from the end
while(lenA > lenB):
ptrA = ptrA->next
lenA--
while(lenB > lenA):
prtB = ptrB->next
lenB--
while(ptrA != NULL):
if (ptrA == ptrB):
return ptrA //found merge point
ptrA = ptrA->next
ptrB = ptrB->next
This is asymptotically the same (linear time) as my other answer but probably has smaller constants, so is probably faster. But I think my other answer is cooler.
If
by "modification is not allowed" it was meant "you may change but in the end they should be restored", and
we could iterate the lists exactly twice
the following algorithm would be the solution.
First, the numbers. Assume the first list is of length a+c and the second one is of length b+c, where c is the length of their common "tail" (after the mergepoint). Let's denote them as follows:
x = a+c
y = b+c
Since we don't know the length, we will calculate x and y without additional iterations; you'll see how.
Then, we iterate each list and reverse them while iterating! If both iterators reach the merge point at the same time, then we find it out by mere comparing. Otherwise, one pointer will reach the merge point before the other one.
After that, when the other iterator reaches the merge point, it won't proceed to the common tail. Instead will go back to the former beginning of the list that had reached merge-point before! So, before it reaches the end of the changed list (i.e. the former beginning of the other list), he will make a+b+1 iterations total. Let's call it z+1.
The pointer that reached the merge-point first, will keep iterating, until reaches the end of the list. The number of iterations it made should be calculated and is equal to x.
Then, this pointer iterates back and reverses the lists again. But now it won't go back to the beginning of the list it originally started from! Instead, it will go to the beginning of the other list! The number of iterations it made should be calculated and equal to y.
So we know the following numbers:
x = a+c
y = b+c
z = a+b
From which we determine that
a = (+x-y+z)/2
b = (-x+y+z)/2
c = (+x+y-z)/2
Which solves the problem.
Well, if you know that they will merge:
Say you start with:
A-->B-->C
|
V
1-->2-->3-->4-->5
1) Go through the first list setting each next pointer to NULL.
Now you have:
A B C
1-->2-->3 4 5
2) Now go through the second list and wait until you see a NULL, that is your merge point.
If you can't be sure that they merge you can use a sentinel value for the pointer value, but that isn't as elegant.
If we could iterate lists exactly twice, than I can provide method for determining merge point:
iterate both lists and calculate lengths A and B
calculate difference of lengths C = |A-B|;
start iterating both list simultaneously, but make additional C steps on list which was greater
this two pointers will meet each other in the merging point
Here's a solution, computationally quick (iterates each list once) but uses a lot of memory:
for each item in list a
push pointer to item onto stack_a
for each item in list b
push pointer to item onto stack_b
while (stack_a top == stack_b top) // where top is the item to be popped next
pop stack_a
pop stack_b
// values at the top of each stack are the items prior to the merged item
You can use a set of Nodes. Iterate through one list and add each Node to the set. Then iterate through the second list and for every iteration, check if the Node exists in the set. If it does, you've found your merge point :)
This arguably violates the "parse each list only once" condition, but implement the tortoise and hare algorithm (used to find the merge point and cycle length of a cyclic list) so you start at List A, and when you reach the NULL at the end you pretend it's a pointer to the beginning of list B, thus creating the appearance of a cyclic list. The algorithm will then tell you exactly how far down List A the merge is (the variable 'mu' according to the Wikipedia description).
Also, the "lambda" value tells you the length of list B, and if you want, you can work out the length of list A during the algorithm (when you redirect the NULL link).
Maybe I am over simplifying this, but simply iterate the smallest list and use the last nodes Link as the merging point?
So, where Data->Link->Link == NULL is the end point, giving Data->Link as the merging point (at the end of the list).
EDIT:
Okay, from the picture you posted, you parse the two lists, the smallest first. With the smallest list you can maintain the references to the following node. Now, when you parse the second list you do a comparison on the reference to find where Reference [i] is the reference at LinkedList[i]->Link. This will give the merge point. Time to explain with pictures (superimpose the values on the picture the OP).
You have a linked list (references shown below):
A->B->C->D->E
You have a second linked list:
1->2->
With the merged list, the references would then go as follows:
1->2->D->E->
Therefore, you map the first "smaller" list (as the merged list, which is what we are counting has a length of 4 and the main list 5)
Loop through the first list, maintain a reference of references.
The list will contain the following references Pointers { 1, 2, D, E }.
We now go through the second list:
-> A - Contains reference in Pointers? No, move on
-> B - Contains reference in Pointers? No, move on
-> C - Contains reference in Pointers? No, move on
-> D - Contains reference in Pointers? Yes, merge point found, break.
Sure, you maintain a new list of pointers, but thats not outside the specification. However the first list is parsed exactly once, and the second list will only be fully parsed if there is no merge point. Otherwise, it will end sooner (at the merge point).
I have tested a merge case on my FC9 x86_64, and print every node address as shown below:
Head A 0x7fffb2f3c4b0
0x214f010
0x214f030
0x214f050
0x214f070
0x214f090
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170
Head B 0x7fffb2f3c4a0
0x214f0b0
0x214f0d0
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170
Note becase I had aligned the node structure, so when malloc() a node, the address is aligned w/ 16 bytes, see the least 4 bits.
The least bits are 0s, i.e., 0x0 or 000b.
So if your are in the same special case (aligned node address) too, you can use these least 4 bits.
For example when travel both lists from head to tail, set 1 or 2 of the 4 bits of the visiting node address, that is, set a flag;
next_node = node->next;
node = (struct node*)((unsigned long)node | 0x1UL);
Note above flags won't affect the real node address but only your SAVED node pointer value.
Once found somebody had set the flag bit(s), then the first found node should be the merge point.
after done, you'd restore the node address by clear the flag bits you had set. while an important thing is that you should be careful when iterate (e.g. node = node->next) to do clean. remember you had set flag bits, so do this way
real_node = (struct node*)((unsigned long)node) & ~0x1UL);
real_node = real_node->next;
node = real_node;
Because this proposal will restore the modified node addresses, it could be considered as "no modification".
There can be a simple solution but will require an auxilary space. The idea is to traverse a list and store each address in a hash map, now traverse the other list and match if the address lies in the hash map or not. Each list is traversed only once. There's no modification to any list. Length is still unknown. Auxiliary space used: O(n) where 'n' is the length of first list traversed.
this solution iterates each list only once...no modification of list required too..though you may complain about space..
1) Basically you iterate in list1 and store the address of each node in an array(which stores unsigned int value)
2) Then you iterate list2, and for each node's address ---> you search through the array that you find a match or not...if you do then this is the merging node
//pseudocode
//for the first list
p1=list1;
unsigned int addr[];//to store addresses
i=0;
while(p1!=null){
addr[i]=&p1;
p1=p1->next;
}
int len=sizeof(addr)/sizeof(int);//calculates length of array addr
//for the second list
p2=list2;
while(p2!=null){
if(search(addr[],len,&p2)==1)//match found
{
//this is the merging node
return (p2);
}
p2=p2->next;
}
int search(addr,len,p2){
i=0;
while(i<len){
if(addr[i]==p2)
return 1;
i++;
}
return 0;
}
Hope it is a valid solution...
There is no need to modify any list. There is a solution in which we only have to traverse each list once.
Create two stacks, lets say stck1 and stck2.
Traverse 1st list and push a copy of each node you traverse in stck1.
Same as step two but this time traverse 2nd list and push the copy of nodes in stck2.
Now, pop from both stacks and check whether the two nodes are equal, if yes then keep a reference to them. If no, then previous nodes which were equal are actually the merge point we were looking for.
int FindMergeNode(Node headA, Node headB) {
Node currentA = headA;
Node currentB = headB;
// Do till the two nodes are the same
while (currentA != currentB) {
// If you reached the end of one list start at the beginning of the other
// one currentA
if (currentA.next == null) {
currentA = headA;
} else {
currentA = currentA.next;
}
// currentB
if (currentB.next == null) {
currentB = headB;
} else {
currentB = currentB.next;
}
}
return currentB.data;
}
We can use two pointers and move in a fashion such that if one of the pointers is null we point it to the head of the other list and same for the other, this way if the list lengths are different they will meet in the second pass.
If length of list1 is n and list2 is m, their difference is d=abs(n-m). They will cover this distance and meet at the merge point.
Code:
int findMergeNode(SinglyLinkedListNode* head1, SinglyLinkedListNode* head2) {
SinglyLinkedListNode* start1=head1;
SinglyLinkedListNode* start2=head2;
while (start1!=start2){
start1=start1->next;
start2=start2->next;
if (!start1)
start1=head2;
if (!start2)
start2=head1;
}
return start1->data;
}
Here is naive solution , No neeed to traverse whole lists.
if your structured node has three fields like
struct node {
int data;
int flag; //initially set the flag to zero for all nodes
struct node *next;
};
say you have two heads (head1 and head2) pointing to head of two lists.
Traverse both the list at same pace and put the flag =1(visited flag) for that node ,
if (node->next->field==1)//possibly longer list will have this opportunity
//this will be your required node.
How about this:
If you are only allowed to traverse each list only once, you can create a new node, traverse the first list to have every node point to this new node, and traverse the second list to see if any node is pointing to your new node (that's your merge point). If the second traversal doesn't lead to your new node then the original lists don't have a merge point.
If you are allowed to traverse the lists more than once, then you can traverse each list to find our their lengths and if they are different, omit the "extra" nodes at the beginning of the longer list. Then just traverse both lists one step at a time and find the first merging node.
Steps in Java:
Create a map.
Start traversing in the both branches of list and Put all traversed nodes of list into the Map using some unique thing related to Nodes(say node Id) as Key and put Values as 1 in the starting for all.
When ever first duplicate key comes, increment the value for that Key (let say now its value became 2 which is > 1.
Get the Key where the value is greater than 1 and that should be the node where two lists are merging.
We can efficiently solve it by introducing "isVisited" field. Traverse first list and set "isVisited" value to "true" for all nodes till end. Now start from second and find first node where flag is true and Boom ,its your merging point.
Step 1: find lenght of both the list
Step 2 : Find the diff and move the biggest list with the difference
Step 3 : Now both list will be in similar position.
Step 4 : Iterate through list to find the merge point
//Psuedocode
def findmergepoint(list1, list2):
lendiff = list1.length() > list2.length() : list1.length() - list2.length() ? list2.lenght()-list1.lenght()
biggerlist = list1.length() > list2.length() : list1 ? list2 # list with biggest length
smallerlist = list1.length() < list2.length() : list2 ? list1 # list with smallest length
# move the biggest length to the diff position to level both the list at the same position
for i in range(0,lendiff-1):
biggerlist = biggerlist.next
#Looped only once.
while ( biggerlist is not None and smallerlist is not None ):
if biggerlist == smallerlist :
return biggerlist #point of intersection
return None // No intersection found
int FindMergeNode(Node *headA, Node *headB)
{
Node *tempB=new Node;
tempB=headB;
while(headA->next!=NULL)
{
while(tempB->next!=NULL)
{
if(tempB==headA)
return tempB->data;
tempB=tempB->next;
}
headA=headA->next;
tempB=headB;
}
return headA->data;
}
Use Map or Dictionary to store the addressess vs value of node. if the address alread exists in the Map/Dictionary then the value of the key is the answer.
I did this:
int FindMergeNode(Node headA, Node headB) {
Map<Object, Integer> map = new HashMap<Object, Integer>();
while(headA != null || headB != null)
{
if(headA != null && map.containsKey(headA.next))
{
return map.get(headA.next);
}
if(headA != null && headA.next != null)
{
map.put(headA.next, headA.next.data);
headA = headA.next;
}
if(headB != null && map.containsKey(headB.next))
{
return map.get(headB.next);
}
if(headB != null && headB.next != null)
{
map.put(headB.next, headB.next.data);
headB = headB.next;
}
}
return 0;
}
A O(n) complexity solution. But based on an assumption.
assumption is: both nodes are having only positive integers.
logic : make all the integer of list1 to negative. Then walk through the list2, till you get a negative integer. Once found => take it, change the sign back to positive and return.
static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
SinglyLinkedListNode current = head1; //head1 is give to be not null.
//mark all head1 nodes as negative
while(true){
current.data = -current.data;
current = current.next;
if(current==null) break;
}
current=head2; //given as not null
while(true){
if(current.data<0) return -current.data;
current = current.next;
}
}
You can add the nodes of list1 to a hashset and the loop through the second and if any node of list2 is already present in the set .If yes, then thats the merge node
static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
HashSet<SinglyLinkedListNode> set=new HashSet<SinglyLinkedListNode>();
while(head1!=null)
{
set.add(head1);
head1=head1.next;
}
while(head2!=null){
if(set.contains(head2){
return head2.data;
}
}
return -1;
}
Solution using javascript
var getIntersectionNode = function(headA, headB) {
if(headA == null || headB == null) return null;
let countA = listCount(headA);
let countB = listCount(headB);
let diff = 0;
if(countA > countB) {
diff = countA - countB;
for(let i = 0; i < diff; i++) {
headA = headA.next;
}
} else if(countA < countB) {
diff = countB - countA;
for(let i = 0; i < diff; i++) {
headB = headB.next;
}
}
return getIntersectValue(headA, headB);
};
function listCount(head) {
let count = 0;
while(head) {
count++;
head = head.next;
}
return count;
}
function getIntersectValue(headA, headB) {
while(headA && headB) {
if(headA === headB) {
return headA;
}
headA = headA.next;
headB = headB.next;
}
return null;
}
If editing the linked list is allowed,
Then just make the next node pointers of all the nodes of list 2 as null.
Find the data value of the last node of the list 1.
This will give you the intersecting node in single traversal of both the lists, with "no hi fi logic".
Follow the simple logic to solve this problem:
Since both pointer A and B are traveling with same speed. To meet both at the same point they must be cover the same distance. and we can achieve this by adding the length of a list to another.

How to determine if a linked list has a cycle using only two memory locations

Does anyone know of an algorithm to find if a linked list loops on itself using only two variables to traverse the list. Say you have a linked list of objects, it doesn't matter what type of object. I have a pointer to the head of the linked list in one variable and I am only given one other variable to traverse the list with.
So my plan is to compare pointer values to see if any pointers are the same. The list is of finite size but may be huge. I can set both variable to the head and then traverse the list with the other variable, always checking if it is equal to the other variable, but, if I do hit a loop I will never get out of it. I'm thinking it has to do with different rates of traversing the list and comparing pointer values. Any thoughts?
I would suggest using Floyd's Cycle-Finding Algorithm aka The Tortoise and the Hare Algorithm. It has O(n) complexity and I think it fits your requirements.
Example code:
function boolean hasLoop(Node startNode){
Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
if (slowNode == fastNode1 || slowNode == fastNode2) return true;
slowNode = slowNode.next();
}
return false;
}
More info on Wikipedia: Floyd's cycle-finding algorithm.
You can use the Turtle and Rabbit algorithm.
Wikipedia has an explanation too, and they call it "Floyd's cycle-finding algorithm" or "Tortoise and hare"
Absolutely. One solution indeed can be traversing the list with both pointers, one travelling at twice the rate of the other.
Start with the 'slow' and the 'fast' pointer pointing to any location in the list. Run the traversal loop. If the 'fast' pointer at any time comes to coincide with the slow pointer, you have a circular linked list.
int *head = list.GetHead();
if (head != null) {
int *fastPtr = head;
int *slowPtr = head;
bool isCircular = true;
do
{
if (fastPtr->Next == null || fastPtr->Next->Next == null) //List end found
{
isCircular = false;
break;
}
fastPtr = fastPtr->Next->Next;
slowPtr = slowPtr->Next;
} while (fastPtr != slowPtr);
//Do whatever you want with the 'isCircular' flag here
}
I tried to solve this myself and found a different (less efficient but still optimal) solution.
The idea is based on reversing a singly linked list in linear time. This can be done by doing two swaps at each step in iterating over the list. If q is the previous element (initially null) and p is the current, then swap(q,p->next) swap(p,q) will reverse the link and advance the two pointers at the same time. The swaps can be done using XOR to prevent having to use a third memory location.
If the list has a cycle then at one point during the iteration you will arrive at a node whose pointer has already been changed. You cannot know which node that is, but by continuing the iteration, swapping some elements twice, you arrive at the head of the list again.
By reversing the list twice, the list remains unchanged in result and you can tell if it had a cycle based on whether you arrived at the original head of the list or not.
int isListCircular(ListNode* head){
if(head==NULL)
return 0;
ListNode *fast=head, *slow=head;
while(fast && fast->next){
if(fast->next->next==slow)
return 1;
fast=fast->next->next;
slow=slow->next;
}
return 0;
}
boolean findCircular(Node *head)
{
Node *slower, * faster;
slower = head;
faster = head->next;
while(true) {
if ( !faster || !faster->next)
return false;
else if (faster == slower || faster->next == slower)
return true;
else
faster = faster->next->next;
}
}
Taking this problem to a next step will be identifying the cycle (that is, not just that the cycle exists, but where exactly it is in the list).
Tortoise and Hare algorithm can be used for the same, however, we will require to keep track of the head of the list at all times. An illustration of this algorithm can be found here.

Resources