参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
面试题 02.07. 链表相交
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:

示例 2:

示例 3:


思路
简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。
为了方便举例,假设节点元素数值相等,则节点指针相等。
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。
C++代码如下:
class Solution {public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* curA = headA;ListNode* curB = headB;int lenA = 0, lenB = 0;while (curA != NULL) { // 求链表A的长度lenA++;curA = curA->next;}while (curB != NULL) { // 求链表B的长度lenB++;curB = curB->next;}curA = headA;curB = headB;// 让curA为最长链表的头,lenA为其长度if (lenB > lenA) {swap (lenA, lenB);swap (curA, curB);}// 求长度差int gap = lenA - lenB;// 让curA和curB在同一起点上(末尾位置对齐)while (gap--) {curA = curA->next;}// 遍历curA 和 curB,遇到相同则直接返回while (curA != NULL) {if (curA == curB) {return curA;}curA = curA->next;curB = curB->next;}return NULL;}};
- 时间复杂度:
#card=math&code=O%28n%20%2B%20m%29)
- 空间复杂度:
#card=math&code=O%281%29)
其他语言版本
Java
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode curA = headA;ListNode curB = headB;int lenA = 0, lenB = 0;while (curA != null) { // 求链表A的长度lenA++;curA = curA.next;}while (curB != null) { // 求链表B的长度lenB++;curB = curB.next;}curA = headA;curB = headB;// 让curA为最长链表的头,lenA为其长度if (lenB > lenA) {//1. swap (lenA, lenB);int tmpLen = lenA;lenA = lenB;lenB = tmpLen;//2. swap (curA, curB);ListNode tmpNode = curA;curA = curB;curB = tmpNode;}// 求长度差int gap = lenA - lenB;// 让curA和curB在同一起点上(末尾位置对齐)while (gap-- > 0) {curA = curA.next;}// 遍历curA 和 curB,遇到相同则直接返回while (curA != null) {if (curA == curB) {return curA;}curA = curA.next;curB = curB.next;}return null;}}
Python
class Solution:def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:"""根据快慢法则,走的快的一定会追上走得慢的。在这道题里,有的链表短,他走完了就去走另一条链表,我们可以理解为走的快的指针。那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个位置相遇"""cur_a, cur_b = headA, headB # 用两个指针代替a和bwhile cur_a != cur_b:cur_a = cur_a.next if cur_a else headB # 如果a走完了,那么就切换到b走cur_b = cur_b.next if cur_b else headA # 同理,b走完了就切换到areturn cur_a
Go
func getIntersectionNode(headA, headB *ListNode) *ListNode {curA := headAcurB := headBlenA, lenB := 0, 0// 求A,B的长度for curA != nil {curA = curA.NextlenA++}for curB != nil {curB = curB.NextlenB++}var step intvar fast, slow *ListNode// 请求长度差,并且让更长的链表先走相差的长度if lenA > lenB {step = lenA - lenBfast, slow = headA, headB} else {step = lenB - lenAfast, slow = headB, headA}for i:=0; i < step; i++ {fast = fast.Next}// 遍历两个链表遇到相同则跳出遍历for fast != slow {fast = fast.Nextslow = slow.Next}return fast}
javaScript
var getListLen = function(head) {let len = 0, cur = head;while(cur) {len++;cur = cur.next;}return len;}var getIntersectionNode = function(headA, headB) {let curA = headA,curB = headB,lenA = getListLen(headA),lenB = getListLen(headB);if(lenA < lenB) {// 下面交换变量注意加 “分号” ,两个数组交换变量在同一个作用域下时// 如果不加分号,下面两条代码等同于一条代码: [curA, curB] = [lenB, lenA][curA, curB] = [curB, curA];[lenA, lenB] = [lenB, lenA];}let i = lenA - lenB;while(i-- > 0) {curA = curA.next;}while(curA && curA !== curB) {curA = curA.next;curB = curB.next;}return curA;};
TypeScript:
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {let sizeA: number = 0,sizeB: number = 0;let curA: ListNode | null = headA,curB: ListNode | null = headB;while (curA) {sizeA++;curA = curA.next;}while (curB) {sizeB++;curB = curB.next;}curA = headA;curB = headB;if (sizeA < sizeB) {[sizeA, sizeB] = [sizeB, sizeA];[curA, curB] = [curB, curA];}let gap = sizeA - sizeB;while (gap-- && curA) {curA = curA.next;}while (curA && curB) {if (curA === curB) {return curA;}curA = curA.next;curB = curB.next;}return null;};
C:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode *l = NULL, *s = NULL;int lenA = 0, lenB = 0, gap = 0;// 求出两个链表的长度s = headA;while (s) {lenA ++;s = s->next;}s = headB;while (s) {lenB ++;s = s->next;}// 求出两个链表长度差if (lenA > lenB) {l = headA, s = headB;gap = lenA - lenB;} else {l = headB, s = headA;gap = lenB - lenA;}// 尾部对齐while (gap--) l = l->next;// 移动,并检查是否有相同的元素while (l) {if (l == s) return l;l = l->next, s = s->next;}return NULL;}

