7.2 KiB
2.7. Intersection
Given 2 singly linked lists, determine if the 2 lists intersect. Return the intersecting node. The intersection is defined based on the reference, not value. If the kth node of the first linked list is the exact same node (by reference) as the jth node of the second linked list, then True
Initial idea
Two nodes in a singly linked list are similar by reference (?) if all values about the object are the same, right? That is, if .next and .data are the same.
public static LinkedListNode intersect(LinkedListNode a, LinkedListNode b){
while(a != null && b != null){
if(a.data == b.data && a.next.data == b.next.data){
return a;
}
a = a.next;
b = b.next;
}
return null;
}
how to evaluate if a.next == b.next? because a.next == c, and c on itself has c.next, and so on. Changing by a.next.data == b.next.data
Hint 1
You can do this in O(A + B) time and O(1) additional space, no need to use a hash table
The previous code doesn't compare all nodes... I should do a nested loop, then it'd be O(AB).
public static LinkedListNode intersect(LinkedListNode a, LinkedListNode b){
LinkedListNode b_reset = b;
while(a != null){
b = b_reset;
while(b != null){
if(a.data == b.data && a.next.data == b.next.data){
return a;
}
b = b.next;
}
a = a.next;
}
return null;
}
Still far away from O(A + B). We cannot iterate A and B at the same time then? How can we compare them?
Hint 2
Draw a picture of intersecting linked lists and two equivalent linked lists (by value) that don't intersect.
Problem is, I don't understand what by value and by reference are.
Hint 3
Focus first on just identifying if there's an intersection
An intersection is two nodes having the same .data?
Hint 4
Two intersecting linked lists always have the same last node. Once they intersect, all the nodes after that will be equal
Ok, this follows my previous idea that .next must also be equal, which means .next.next also, until the end. We can iterate to the last node of the list, check if they match, and then find the diverting node. How to find the diverting node is another topic
public static LinkedListNode intersect(LinkedListNode a, LinkedListNode b){
while(a.next != null){
a = a.next;
}
while(b.next != null){
b = b.next;
}
if(a.data == b.data){
// do things
LinkedListNode ane = null;
return ane;
}
return null;
}
Hint 5
You can determine if two linked lists intersect by traversing to the end of each and comparing their tails
Gotcha
Hint 6
Now need to find the intersection, how to do this if len(A) == len(B)?
Ideally I would iterate backwards, but that's not possible... Maybe with two pointers. What about:
- Iterate through both
- If
a.data == b.data, savea. - Keep checking the condition. If it's not met, reset.
- If
a.data == b.data, savea. - Reach the end, with saved
anode.
Of course, they need to have the same length. This would be O(3A) time and O(1) space.
public static LinkedListNode intersect(LinkedListNode a, LinkedListNode b){
LinkedListNode a_head = a;
LinkedListNode b_head = b;
// iterate through A
while(a_head.next != null){
a_head = a_head.next;
}
// iterate through B
while(b_head.next != null){
b_head = b_head.next;
}
// last node inequal, return null
if(a_head.data != b_head.data) return null;
// there's intersection
LinkedListNode inters = null;
while(a.next != null && b.next != null){
// nodes with same data found
if(a.data == b.data){
// no intersecting node, set to a
if(inters == null){
inters = a;
}
// if nodes are sme and reset = true, keep iterating
}
// nodes aren't the same, reset inters
else{
inters = null;
}
a = a.next;
b = b.next;
}
if(inters == null) return a;
return inters;
}
This should work, in the worst case the intersecting node is the tail itself. If they have a different length:
- Get both lengths
- Get minimum length, and advance the pointer of the longest list minlen positions. Then start algorithm
public static LinkedListNode intersect(LinkedListNode a, LinkedListNode b){
LinkedListNode a_head = a;
LinkedListNode b_head = b;
int a_len, b_len = 1;
// iterate through A
while (a_head.next != null){
a_head = a_head.next;
a_len += 1;
}
// iterate through B
while (b_head.next != null){
b_head = b_head.next;
b_len += 1;
}
// last node inequal, return null
if (a_head.data != b_head.data) return null;
// compare lengths, adjust node
if (a_len == 1 or b_len == 1) return a_head;
if (a_len < b_len){
while (a_len > 0){
b = b.next;
}
}
else if (b_len < a_len){
while (b_len > 0){
a = a.next;
}
}
// there's intersection
LinkedListNode inters = null;
while(a.next != null && b.next != null){
// nodes with same data found
if(a.data == b.data){
// no intersecting node, set to a
if(inters == null){
inters = a;
}
// if nodes are sme and reset = true, keep iterating
}
// nodes aren't the same, reset inters
else{
inters = null;
}
a = a.next;
b = b.next;
}
if(inters == null) return a;
return inters;
}
And this should work for lists of all possible lengths.
Hint 7
If the two linked lists had the same length, you could trasverse forward in each until you found an element in common. How do you adjust this for lists of different lengths?
Get the length difference, move the pointer of the longer one minlen times.
Hint 8
Try using the difference between the lengths of the two linked lists
Yep.
Hint 9
If you move a pointer in the longer linked list forward by the difference in lengths, you can then apply a similar approach to the scenario when the linked lists are equal.
Already got that.
Solution
The algorithm is the same as mine
- Get lengths and tails of each list
- Compare the tails, if they are different (by reference, not by value) return null
- Set two pointers to the start
- On the longer linked list, advance its pointer by the difference in lengths
- Trasverse on each linked list until the pointers are the same
Takeaways:
size++is possible in java, nosize += 1necessary- When comparing nodes, compare
a == b, nota.data == b.data - Get a new class for the tail and lengths
Improved algorithm in 2.7. intersection.java. Because we're comparing by reference not value, the condition in while won't be met if two nodes have the same .data but different .next.
Update
New solution found at stackoverflow, without any pointers.