相交链表【2.23】

题目:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
在这里插入图片描述
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

示例 1:
在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

解题思路:
1.在这里插入图片描述

时间复杂度O(n)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null || headB==null) return null;
        //双指针法
        ListNode a=headA;
        ListNode b=headB;
        while(a!=b){
            a=a==null?headB:a.next;
            b=b==null?headB:b.next;
        }
        return a;

    }
}

2.先计算得到每个链表的长度,然后长度相减得到间隔diff。
长链表从第diff个元素开始移动
在这里插入图片描述
时间复杂度O(n+m)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA,ListNode headB){
        int L1=0,L2=0,diff=0;
        ListNode head1 = headA,head2 = headB;
        while(head1 != null){
            L1++;
            head1 = head1.next;
        }
        while(head2 != null){
        L2++;
        head2 = head2.next;
        }
        if(L1 <L2){
            head1=headB;
            head2=headA;
            diff=L2-L1;
        }
        else{
            head1 = headA;
            head2=headB;
            diff=L1-L2;
            }
        for(int i = 0; i < diff; i++){
            head1 = head1.next;
        }
        while(head1 != null && head2 !=null){
            if(head1 == head2){
                return head1;
            }
            head1= head1.next;
            head2= head2.next;
        }
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++相交链表的完整代码,其中包括了两种不同的解法: 解法一:常规遍历方法 ``` class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { // 如果单链表A和单链表B至少有一个为空,则两个单链表不存在相交节点,返回null if(headA == nullptr || headB == nullptr) { return nullptr; } // 记录经过的所有节点 // 注意!这里记录的是单链表的节点,不是节点的值 unordered_set<ListNode *> visited; // 记录当前节点 ListNode *p=headA; // 循环遍历单链表A while(p!=nullptr) { // 保存访问过的节点 visited.insert(p); // 访问下一个节点 p=p->next; } // 遍历完单链表A后继续遍历单链表B p=headB; // 循环遍历单链表B while(p!=nullptr) { // 如果当前节点存在于已访问过的节点中 if(visited.count(p)) { // 则当前节点就是相交节点 return p; } // 访问下一个节点 p=p->next; } // 两个单链表不存在相交节点,返回null return nullptr; } }; ``` 解法二:基于双指针的方法 ``` class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { // 如果单链表A和单链表B至少有一个为空,则两个单链表不存在相交节点,返回null if(headA == nullptr || headB == nullptr) { return nullptr; } // 定义两个指针分别指向两个单链表的头节点 ListNode *pA=headA; ListNode *pB=headB; // 在两个指针相遇之前,持续遍历两个单链表 while(pA!=pB) { // 如果单链表A遍历结束 if(pA==nullptr) { // 将pA指向单链表B的头节点 pA=headB; } else { // 否则继续遍历 pA=pA->next; } // 如果单链表B遍历结束 if(pB==nullptr) { // 将pB指向单链表A的头节点 pB=headA; } else { // 否则继续遍历 pB=pB->next; } } // 两个指针相遇之后 // 相遇点即为两个单链表相交节点 return pA; } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值