判断两个链表是否相交

这是一道比较综合的题目。将链表中关于环和相交的问题聚集在一起了,关键是要思路清晰。

思路如下:

/*
     * 判断链表是否有环
     *     1 如果一个有环一个无环,则肯定不相较
     *     2 如果都无环,则遍历到尾部,看看最后一个节点是否相等即可
     *          如果要找到第一个相交的点,则让长的链表先走len1-len2步,再同时走,找到相等的节点即可
     *     3 如果都有环,则先找到各自的环入口点(快慢指针,第一次相遇后,快指针从头节点开始,每次走一步,慢指针继续向前走一步,直至再次相遇)
     *          如果两个入口点相等,则肯定相交
     *              如果要找到第一个相交的点,则需要让长的链表(从头节点到相交的节点)先走len1-len2步,然后同时走,找到相等的点即可
     *          如果两个入口点不相等,则选其中一个相交点,继续向后走,看看 是否会经历另外一个相交点,如果经历了,则相交,否则不相交
     */

具体代码如下:

public boolean chkInter(ListNode head1, ListNode head2, int adjust0, int adjust1) {
        if(head1==null || head2==null) return false;
        ListNode node1 = chkLoop(head1);
        ListNode node2 = chkLoop(head2);
        //判断是否有环
        if(node1==null && node2==null) { //两个都是无环链表
            while(head1.next!=null) {
                head1 = head1.next;
            }
            while(head2.next !=null) {
                head2 = head2.next;
            }
            if(head1==head2) {
                return true;
            } else {
                return false;
            }
        } else if(node1!=null && node2!=null) {//两个都是有环链表
            //node1和node2是环的入口点
            if(node1==node2) {
                return true;
            } else {
                ListNode cur = node1.next;
                while(cur!=node1) {
                    if(cur == node2) { //相交
                        return true;
                    }
                    cur = cur.next;
                }
                //不相交
                return false;
            }
        } else { //一个有环一个无环
            return false;
        }
    }

    private ListNode chkLoop(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast!=null && fast.next!=null) {
            slow = slow.next;
            fast = fast.next.next;
            if(slow==fast) {
                break;
            }
        }
        //没有环则返回null
        if(fast==null || fast.next==null) return null;
        fast = head;
        while(slow!=fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值