LeetCode 面试题 02.07.链表相交

题目描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

提示:

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 0 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]

进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?

思路

题目要求求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。

首先要求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB末尾对齐的位置。此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。否则循环退出返回空指针。

代码

C++版:

正确的解法:

/**
 * 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* curA=headA;
        ListNode* curB=headB;
        int lenA=0,lenB=0;
        // 首先需要分别求出两链表的长度
        while(curA!=nullptr){
            lenA++;
            curA=curA->next;    
        }
        while(curB!=nullptr){
            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 != nullptr) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return nullptr;
    }
};

错误的解法:忽略了A和B链表在相交之前已有元素相同的情况。

/**
 * 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) {
        // 双指针法
        // 当curA和curB其中一个到达nullptr时,则另一个所在的位置可能是两个链表的相交节点
        ListNode* curA=headA;
        ListNode* curB=headB;
        ListNode* result;
        while(curA!=nullptr && curB!=nullptr){
            curA=curA->next;
            curB=curB->next;
        }
        // 判断是否为相交节点
        if(curB==nullptr){
            curB=headB;
            while(curB!=nullptr && curB!=curA ){
                curB=curB->next;
            }
            if(curB==nullptr){
                result=nullptr;
            }else{
                result=curA;
            }
        }
        if(curA==nullptr){
            curA=headA;
            while(curA!=nullptr && curB!=curA ){
                curA=curA->next;
            }
            if(curA==nullptr){
                result=nullptr;
            }else{
                result=curB;
            }
        }
        return result;
    }
};

Python版:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        curA=headA
        curB=headB
        lenA, lenB = 0, 0
        while curA:         # 求链表A的长度
            lenA += 1
            curA = curA.next 
        while curB:         # 求链表B的长度
            lenB += 1
            curB = curB.next
        curA, curB = headA, headB
        if lenB > lenA:
            curA, curB = curB, curA
            lenA, lenB = lenB, lenA 
        for _ in range(lenA - lenB):  # 让curA和curB在同一起点上(末尾位置对齐)
            curA = curA.next
        while curA:         #  遍历curA 和 curB,遇到相同则直接返回
            if curA == curB:
                return curA
            else:
                curA = curA.next 
                curB = curB.next
        return None
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值