# 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.

```java
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).

```java
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

```java
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:

1. Iterate through both
2. If `a.data == b.data`, save `a`.
3. Keep checking the condition. If it's not met, reset.
4. If `a.data == b.data`, save `a`.
5. Reach the end, with saved `a` node.

Of course, they need to have the same length. This would be O(3A) time and O(1) space.

```java
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:

1. Get both lengths
2. Get minimum length, and advance the pointer of the longest list minlen positions. Then start algorithm

```java
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

1. Get lengths and tails of each list
2. Compare the tails, if they are different (**by reference, not by value**) return null
3. Set two pointers to the start
4. On the longer linked list, advance its pointer by the difference in lengths
5. Trasverse on each linked list until the pointers are the same

Takeaways:

* `size++` is possible in java, no `size += 1` necessary
* When comparing nodes, compare `a == b`, not `a.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](https://stackoverflow.com/questions/1594061/check-if-two-linked-lists-merge-if-so-where/14956113#14956113), without any pointers.
