这道题是一道很有意思的题目,值得看一下。
题目大意是:给定两个链表,这两个链表和平时遇到的链表的区别在于他们最终有可能汇聚在一相同的一点上,如图所示,
但是,并非一定能重合。如果有重合点,返回该重合点,如果没有返回NULL。
假设我们考虑一种比较极端的情况,就是在回合之前,两个链表的节点数是相等的,那么,同时向后便利节点,一定能找到汇聚的情况,即使是两个不相交的链表,最终也会汇聚到NULL地址上。但是问题就处在两个链表在汇聚之前可能前面节点数目不相等,那如果不知道相差节点的数目很可能就会错过,也就是说,我们只要知道相差节点的个数是多少,就很容易知道规划两条链表该怎么走。
因为两个链表是要最终汇聚的,所以,他们汇聚之后的长度是一样的,那两个链表节点数目的差值就是汇聚之前两个链表节点数目的差值,所以,思路就明确了:
思路一:分别遍历两个链表,求出链表长度,得到差值K,长链表从起始节点开始向后走K个节点后,然后两个链表一起向后遍历,寻找汇聚点,不管想不想交都能找出来,因为链表的最后一位是NULL,其实也是汇聚在一起的。代码简单,大家自己调试就好。
思路二:我主要是想引出思路二,这是我看了大神的代码后,觉得思路非常巧妙,而且代码极为精简,具体是这样的,两个指针,一个指针先遍历链表1再遍历链表2,另一个指针先遍历链表2再遍历链表1,通过这种方式,大家会发现,两个指针计划遍历的节点总数是相同的,都是两个链表的长度之和,而刚刚我也说过,从汇聚点开始向后,两个链表的长度是相同的,那么,两个指针在汇聚之前所遍历的节点数就是相同的,两个指针相当于本别走了两个长度一样的长链表,每个链表的组成就是链表1和链表2的顺序颠倒,但是不管怎么样的顺序,两个长链表结尾都是链表1和链表2的公共部分,既然该点的后半段完全一样的,那么前半段也应该是一样的。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *A = headA, *B = headB;
while (A != B) {
A = A ? A->next:headB;
B = B ? B->next:headA;
}
return A;
}
};