|
| 1 | +# 相交链表 |
| 2 | + |
| 3 | +#### *Intersection of Two Linked Lists* |
| 4 | + |
| 5 | +给你两个单链表的头节点 `headA` 和 `headB` ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 `null` 。 |
| 6 | + |
| 7 | +图示两个链表在节点 `c1` 开始相交: |
| 8 | +/160_statement.png) |
| 9 | + |
| 10 | +题目数据 保证 整个链式结构中不存在环。 |
| 11 | + |
| 12 | +注意,函数返回结果后,链表必须保持其原始结构。 |
| 13 | + |
| 14 | + |
| 15 | +提示: |
| 16 | + |
| 17 | +`listA` 中节点数目为 `m` |
| 18 | +`listB` 中节点数目为 `n` |
| 19 | +0 <= m, n <= 3 * 104 |
| 20 | +1 <= Node.val <= 105 |
| 21 | +0 <= skipA <= m |
| 22 | +0 <= skipB <= n |
| 23 | +如果 `listA` 和 `listB` `没有交点,intersectVal` 为 `0` |
| 24 | +如果 `listA` 和 `listB` 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1] |
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | +英文题目: |
| 29 | + |
| 30 | +Given the heads of two singly linked-lists `headA` and `headB`, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return `null`. |
| 31 | + |
| 32 | +For example, the following two linked lists begin to intersect at node `c1`: |
| 33 | +/160_statement.png) |
| 34 | + |
| 35 | +The test cases are generated such that there are no cycles anywhere in the entire linked structure. |
| 36 | + |
| 37 | +**Note** that the linked lists must **retain their original** structure after the function returns. |
| 38 | + |
| 39 | +Custom Judge: |
| 40 | + |
| 41 | +The inputs to the **judge** are given as follows (your program is **not** given these inputs): |
| 42 | + |
| 43 | +`intersectVal` - The value of the node where the intersection occurs. This is 0 if there is no intersected node. |
| 44 | + |
| 45 | +`listA` - The first linked list. |
| 46 | + |
| 47 | +`listB` - The second linked list. |
| 48 | + |
| 49 | +`skipA` - The number of nodes to skip ahead in listA (starting from the head) to get to the intersected node. |
| 50 | + |
| 51 | +`skipB` - The number of nodes to skip ahead in listB (starting from the head) to get to the intersected node. |
| 52 | + |
| 53 | +The judge will then create the linked structure based on these inputs and pass the two heads, headA and headB to your program. If you correctly return the intersected node, then your solution will be **accepted**. |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +**example 1** |
| 58 | +/160_example_1.png) |
| 59 | + |
| 60 | +``` |
| 61 | +Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 |
| 62 | +Output: Intersected at '8' |
| 63 | +Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). |
| 64 | +From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. |
| 65 | + |
| 66 | +``` |
| 67 | + |
| 68 | + |
| 69 | +**example 2** |
| 70 | +/160_example_2.png) |
| 71 | + |
| 72 | +``` |
| 73 | +Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 |
| 74 | +Output: Intersected at '2' |
| 75 | +Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). |
| 76 | +From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B. |
| 77 | + |
| 78 | +``` |
| 79 | + |
| 80 | +**example 3** |
| 81 | +/160_example_3.png) |
| 82 | + |
| 83 | +``` |
| 84 | +Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 |
| 85 | +Output: No intersection |
| 86 | +Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values. |
| 87 | +Explanation: The two lists do not intersect, so return null. |
| 88 | + |
| 89 | +``` |
| 90 | + |
| 91 | + |
| 92 | +**Constraints:** |
| 93 | + |
| 94 | +The number of nodes of listA is in the m. |
| 95 | + |
| 96 | +The number of nodes of listB is in the n. |
| 97 | + |
| 98 | +0 <= m, n <= 3 * 104 |
| 99 | + |
| 100 | +1 <= Node.val <= 105 |
| 101 | + |
| 102 | +0 <= skipA <= m |
| 103 | + |
| 104 | +0 <= skipB <= n |
| 105 | + |
| 106 | +intersectVal is 0 if listA and listB do not intersect. |
| 107 | + |
| 108 | +intersectVal == listA[skipA] == listB[skipB] if listA and listB intersect. |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | +--- |
| 113 | + |
| 114 | +### 思路 |
| 115 | + |
| 116 | +1. 解决这个问题的关键是,通过某些方式,让 `p1` 和 `p2` 能够同时到达相交节点 `c1` |
| 117 | +2. 我们可以让 `p1` 遍历完链表 `A` 之后开始遍历链表 `B`,让 `p2` 遍历完链表 `B` 之后开始遍历链表 `A`,这样相当于「逻辑上」两条链表接在了一起。如果这样进行拼接,就可以让 `p1` 和 `p2` 同时进入公共部分,也就是同时到达相交节点 `c1` |
| 118 | +3. 具体原理如下图 |
| 119 | +/2.jpeg) |
| 120 | + |
| 121 | + |
| 122 | +### 代码 |
| 123 | +``` |
| 124 | + |
| 125 | +/* |
| 126 | + * @lc app=leetcode id=160 lang=cpp |
| 127 | + * |
| 128 | + * [160] Intersection of Two Linked Lists |
| 129 | + */ |
| 130 | + |
| 131 | +// @lc code=start |
| 132 | +/** |
| 133 | + * Definition for singly-linked list. |
| 134 | + * struct ListNode { |
| 135 | + * int val; |
| 136 | + * ListNode *next; |
| 137 | + * ListNode(int x) : val(x), next(NULL) {} |
| 138 | + * }; |
| 139 | + */ |
| 140 | +class Solution { |
| 141 | +public: |
| 142 | + ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { |
| 143 | + // ListNode *pA = headA; |
| 144 | + // ListNode *pB = headB; |
| 145 | + // bool AtoB = false; |
| 146 | + // bool BtoA = false; |
| 147 | + // while (pA != nullptr && pB != nullptr) |
| 148 | + // { |
| 149 | + // pA = pA->next; |
| 150 | + // pB = pB->next; |
| 151 | + // if (pA == nullptr && !AtoB) |
| 152 | + // { |
| 153 | + // pA = headB; |
| 154 | + // AtoB = true; |
| 155 | + // } |
| 156 | + // if (pB == nullptr && !BtoA) |
| 157 | + // { |
| 158 | + // pB = headA; |
| 159 | + // BtoA = true; |
| 160 | + // } |
| 161 | + |
| 162 | + // if (pA == pB) |
| 163 | + // return pA; |
| 164 | + // } |
| 165 | + // return nullptr; |
| 166 | + |
| 167 | + |
| 168 | + // p1 指向 A 链表头结点,p2 指向 B 链表头结点 |
| 169 | + ListNode *p1 = headA, *p2 = headB; |
| 170 | + // p1 和 p2 同时走到链表尾部,null时 null == null 跳出循环,代表无交叉点 |
| 171 | + while (p1 != p2) { |
| 172 | + // p1 走一步,如果走到 A 链表末尾,转到 B 链表 |
| 173 | + if (p1 == nullptr) |
| 174 | + p1 = headB; |
| 175 | + else |
| 176 | + p1 = p1->next; |
| 177 | + // p2 走一步,如果走到 B 链表末尾,转到 A 链表 |
| 178 | + if (p2 == nullptr) |
| 179 | + p2 = headA; |
| 180 | + else |
| 181 | + p2 = p2->next; |
| 182 | + } |
| 183 | + return p1; |
| 184 | + } |
| 185 | +}; |
| 186 | +// @lc code=end |
| 187 | + |
| 188 | + |
| 189 | + |
| 190 | + |
| 191 | +``` |
| 192 | + |
| 193 | +本题以及其它leetcode题目代码github地址: [github地址](https:github.com/SherlockUnknowEn/leetcode) |
0 commit comments