|
| 1 | +题目来源于LeetCode上第160号问题:相交链表。题目难度为Easy,目前通过率54.4%。 |
| 2 | +##题目描述 |
| 3 | +编写一个程序,找到两个单链表相交的起始节点。 |
| 4 | +如下面的两个链表: |
| 5 | + |
| 6 | +在节点 c1 开始相交。 |
| 7 | +示例 1: |
| 8 | + |
| 9 | +``` |
| 10 | +输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 |
| 11 | +输出:Reference of the node with value = 8 |
| 12 | +输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。 |
| 13 | +``` |
| 14 | +注意: |
| 15 | +- 如果两个链表没有交点,返回 null。 |
| 16 | +- 在返回结果后,两个链表仍须保持原有的结构。 |
| 17 | +- 可假定整个链表结构中没有循环。 |
| 18 | +- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。 |
| 19 | + |
| 20 | +##题目解析 |
| 21 | +为满足题目时间复杂度和空间复杂度的要求,我们可以使用双指针法。 |
| 22 | +- 创建两个指针pA和pB分别指向链表的头结点headA和headB。 |
| 23 | +- 当pA到达链表的尾部时,将它重新定位到链表B的头结点headB,同理,当pB到达链表的尾部时,将它重新定位到链表A的头结点headA。 |
| 24 | +- 当pA与pB相等时便是两个链表第一个相交的结点。 |
| 25 | +这里其实就是相当于把两个链表拼在一起了。pA指针是按B链表拼在A链表后面组成的新链表遍历,而pB指针是按A链表拼在B链表后面组成的新链表遍历。举个简单的例子: |
| 26 | +A链表:{1,2,3,4} |
| 27 | +B链表:{6,3,4} |
| 28 | +pA按新拼接的链表{1,2,3,4,6,3,4}遍历 |
| 29 | +pB按新拼接的链表{6,3,4,1,2,3,4}遍历 |
| 30 | + |
| 31 | +##动画理解 |
| 32 | + |
| 33 | + |
| 34 | + |
| 35 | +##代码实现 |
| 36 | +``` |
| 37 | +/** |
| 38 | + * Definition for singly-linked list. |
| 39 | + * struct ListNode { |
| 40 | + * int val; |
| 41 | + * ListNode *next; |
| 42 | + * ListNode(int x) : val(x), next(NULL) {} |
| 43 | + * }; |
| 44 | + */ |
| 45 | +class Solution { |
| 46 | +public: |
| 47 | + ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { |
| 48 | + ListNode *pA = headA; |
| 49 | + ListNode *pB = headB; |
| 50 | + while(pA != pB){ |
| 51 | + if(pA != NULL){ |
| 52 | + pA = pA->next; |
| 53 | + }else{ |
| 54 | + pA = headB; |
| 55 | + } |
| 56 | + if(curB != NULL){ |
| 57 | + pB = pB->next; |
| 58 | + }else{ |
| 59 | + pB = headA; |
| 60 | + } |
| 61 | + } |
| 62 | + return pA; |
| 63 | + } |
| 64 | +}; |
| 65 | +``` |
| 66 | +##复杂度分析 |
| 67 | +- 时间复杂度:O(m+n)。 |
| 68 | +- 空间复杂度:O(1) |
0 commit comments