判断2个链表是否相交,如果相交,求出交点

本文探讨了两个链表相交的判断方法及交点查找算法。通过对比链表尾结点来判断是否相交,并介绍了如何定位第一个相交节点的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果2个链表相交,一定有相同的尾结点

思路:分别遍历找到尾结点,比较,若相同则相交,否则不相交。如果相交,求出交点

public class XiangJiao {
    public static void main(String[] args){
        Node p1=new Node(5);
        Node p2=new Node(3);
        Node p3=new Node(9);
        Node p4=new Node(2);
        p1.next=p2;
        p2.next=p3;
        p3.next=p4;
        Node q1=new Node(6);
        Node q2=new Node(4);
        Node q3=new Node(7);
        Node q4=new Node(8);
        Node q5=new Node(2);
        q1.next=q2;
        q2.next=q3;
        q3.next=q4;
        q4.next=q5;
        System.out.println(new XiangJiao().isIntersect(p1,q1));
        Node n=getMeetNode(p1,q1);
        System.out.println(n.data);
    }
    public boolean isIntersect(Node h1,Node h2){
        if(h1==null||h2==null)
            return false;
        Node t1=h1;
        //找链表1的尾结点
        while(t1.next!=null)
            t1=t1.next;

        Node t2=h2;

        //找链表2的尾结点
        while(t2.next!=null)
            t2=t2.next;

        return t1.data==t2.data;


    }
    //判断是否相交,如果相交找出交点

    public  static Node getMeetNode(Node h1,Node h2){
        if(h1==null||h2==null)
            return null;
        Node t1=h1;
        int len1=1;
        //找链表1的尾结点
        while(t1.next!=null) {
            t1 = t1.next;
            len1++;
        }
        Node t2=h2;
        int len2=1;
        //找链表2的尾结点
        while(t2.next!=null) {
            t2 = t2.next;
            len2++;
        }
        //如果不相交
        if(t1.data!=t2.data){
            return null;
        }
        Node t_1=h1;
        Node t_2=h2;
        //找出较长的,先遍历
        if(len1>len2){
            int d=len1-len2;
            while (d!=0){
                t_1=t_1.next;
                d--;
            }
        }else{
            int d=len2-len1;
            while (d!=0){
                t_2=t_2.next;
                d--;
            }
        }
        while(t_1.data!=t_2.data){//同时遍历
            t_1=t_1.next;
            t_2=t_2.next;
        }
        return t_1;


    }

}

 

 

 

 

<think>好的,我现在需要帮助用户了解如何用Java判断两个链表是否相交。首先,我得回想一下链表相交的定义。链表相交指的是两个链表在某个节点之后合并,形成共同的部分。也就是说,从相交节点开始,后续的所有节点都是相同的,直到链表结束。 接下来,我得确定用户的需求。用户可能正在学习数据结构,或者在面试准备中遇到了这个问题。他们需要具体的实现方法,而不仅仅是理论上的解释。因此,我应该提供清晰的思路和代码示例,同时考虑时间和空间复杂度。 首先,我得回顾常见的解决方法。常见的方法有两种:哈希表法和双指针法。哈希表法的思路是遍历第一个链表,将每个节点的引用存入哈希表,然后遍历第二个链表,检查是否有节点存在于哈希表中。这种方法的时间复杂度是O(m+n),空间复杂度也是O(m+n),其中m和n分别是两个链表的长度。 另一种方法是双指针法,也称为“走尾指针法”。这种方法不需要额外空间,时间复杂度同样是O(m+n)。具体步骤是:首先遍历两个链表找到各自的尾节点,并记录长度。如果尾节点不同,说明不相交;如果相同,则计算两个链表的长度差,让较长的链表的指针先移动差值步,然后两个指针同时移动,直到相遇,相遇点即为相交节点。 用户可能更倾向于高效的方法,尤其是空间复杂度低的解决方案。因此,我应该重点解释双指针法,因为它更优。同时,我需要考虑链表可能存在的环的情况,但通常在这种情况下,题目假设链表无环,所以可能不需要处理环的问题,但最好在注意事项中提及。 然后,我需要考虑如何用Java实现双指针法。首先,定义链表节点的结构,通常是一个包含数据和next指针的类。然后,编写函数来检查相交。具体步骤包括遍历链表获取长度和尾节点,比较尾节点是否相同,调整指针起点,同步遍历直到找到相同节点。 在代码实现中,需要注意边界情况,例如其中一个链表为空,或者两个链表长度相差较大。此外,测试用例的构造也很重要,例如创建相交链表和不相交链表来验证代码的正确性。 可能用户还会有疑问,比如如何处理有环的情况,或者是否有其他方法。虽然问题通常假设链表无环,但可以简要说明如果有环的话需要先检测环,然后再处理相交的问题,但这会增加复杂度。 最后,总结思路和步骤,确保用户能够理解并实现该算法。同时,强调时间和空间复杂度,帮助用户评估不同方法的优劣。</think>--- 要判断两个链表是否相交,关键在于找到**相交节点**(两个链表的公共节点)。Java中可通过以下两种方法实现: --- ### 方法一:哈希表法 **核心思路**:遍历链表A,将所有节点存入哈希表,再遍历链表B,检查节点是否存在于哈希表中。 **时间复杂度**:$O(m + n)$,空间复杂度:$O(m)$(m、n为链表长度) ```java import java.util.HashSet; public class LinkedListIntersection { static class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public ListNode getIntersectionNode(ListNode headA, ListNode headB) { HashSet<ListNode> visited = new HashSet<>(); // 遍历链表A,存储所有节点 while (headA != null) { visited.add(headA); headA = headA.next; } // 遍历链表B,检查哈希表 while (headB != null) { if (visited.contains(headB)) { return headB; } headB = headB.next; } return null; } } ``` --- ### 方法二:双指针法(推荐) **核心思路**: 1. 若两链表相交,则**尾节点必相同** 2. 计算两链表长度差,对齐起点后同步遍历 **时间复杂度**:$O(m + n)$,空间复杂度:$O(1)$ ```java public class LinkedListIntersection { static class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; // 计算链表A和B的长度 int lenA = getLength(headA), lenB = getLength(headB); // 对齐起点:长链表先走差值步 ListNode pA = headA, pB = headB; if (lenA > lenB) { for (int i = 0; i < lenA - lenB; i++) pA = pA.next; } else { for (int i = 0; i < lenB - lenA; i++) pB = pB.next; } // 同步遍历找交点 while (pA != null && pB != null) { if (pA == pB) return pA; pA = pA.next; pB = pB.next; } return null; } private int getLength(ListNode node) { int len = 0; while (node != null) { len++; node = node.next; } return len; } } ``` --- ### 方法三:巧妙双指针遍历(无长度计算) **核心思想**:两指针分别遍历A+B和B+A路径,最终会在交点相遇(若存在)。 ```java public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode pA = headA, pB = headB; // 当pA和pB走过相同路径长度时: // - 若相交,会在交点相遇 // - 若不相交,最终同时为null退出循环 while (pA != pB) { pA = (pA == null) ? headB : pA.next; pB = (pB == null) ? headA : pB.next; } return pA; } ``` --- ### 验证相交的关键条件 1. **尾节点相同**:若两链表尾节点不同,则一定不相交 2. **节点引用相同**:判断相交的依据是节点对象地址相同,而非值相等 --- ### 测试用例示例 ```java public static void main(String[] args) { // 构造相交链表 ListNode common = new ListNode(8); common.next = new ListNode(4); common.next.next = new ListNode(5); ListNode headA = new ListNode(4); headA.next = new ListNode(1); headA.next.next = common; ListNode headB = new ListNode(5); headB.next = new ListNode(6); headB.next.next = new ListNode(1); headB.next.next.next = common; // 调用方法判断 ListNode result = getIntersectionNode(headA, headB); System.out.println(result != null ? "相交节点值:" + result.val : "不相交"); } ``` --- ### 复杂度对比 | 方法 | 时间复杂度 | 空间复杂度 | 适用场景 | |------------|------------|------------|--------------------| | 哈希表法 | $O(m+n)$ | $O(m)$ | 需要快速实现 | | 双指针法 | $O(m+n)$ | $O(1)$ | 内存敏感场景 | | 路径对齐法 | $O(m+n)$ | $O(1)$ | 代码简洁,无需长度 | --- ### 注意事项 1. 若链表可能有环,需先检测环再判断相交(经典相交问题通常假设无环) 2. 节点值可以重复,判断依据是节点引用地址相同而非值相等 3. 空链表直接返回`null`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值