题目描述:编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表**:**
在节点 c1 开始相交。
eg:
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。思路描述:最简单的方法莫过于把两个单链表都存一下,然后遍历一遍是否有相同的节点即可。时间复杂度O(n^2),但是会超时。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
vector<ListNode*> nodesA, nodesB;
while(headA){
nodesA.push_back(headA);
headA = headA->next;
}
while(headB){
nodesB.push_back(headB);
headB = headB->next;
}
for(int i = 0; i < nodesA.size(); i ++)
for(int j = 0; j < nodesB.size(); j ++){
if(nodesA[i] == nodesB[j])
return nodesA[i];
}
return NULL;
}
};我们逆向思维考虑一下,两个链表相交点后面的都是相等的,那么只要从后往前遍历找到不相等的部分就好了。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
vector<ListNode*> nodesA, nodesB;
while(headA){
nodesA.push_back(headA);
headA = headA->next;
}
while(headB){
nodesB.push_back(headB);
headB = headB->next;
}
if(nodesA.size() == 0 || nodesB.size() == 0) return NULL;
int i = nodesA.size() - 1, j = nodesB.size() - 1;
if(nodesA[i] != nodesB[j]) return NULL;
while(i >= 0 && j >= 0){
cout << nodesA[i]->val;
if(nodesA[i] != nodesB[j]){
return nodesA[i + 1];
}
i --; j --;
}
return nodesA[i + 1];
}
};双指针法
创建两个指针 pA 和 pB,分别初始化为链表
A和B的头结点。然后让它们向后逐结点遍历。当 pA到达链表的尾部时,将它重定位到链表
B的头结点 (你没看错,就是链表B); 类似的,当 pB到达链表的尾部时,将它重定位到链表A的头结点。若在某一时刻 pA 和 pB 相遇,则 pA/pB 为相交结点。
不得不说想不到,nb
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* pA = headA, *pB = headB;
int circle = 0;
while(1){
if(pA == pB) return pA;
if(pA) pA =pA->next;
else if(circle == 0) {
pA = headB; circle = 1;
} else return NULL;
if(pB) pB = pB->next;
else pB = headA;
}
return NULL;
}
};