leetcode:求两个链表的交点+求环形链表的入环点

1.求两个链表的交点

https://leetcode-cn.com/problems/intersection-of-two-linked-lists/description/

2.求环形链表的入环点

https://leetcode-cn.com/problems/linked-list-cycle-ii/description/

一、

        首先要判断两个链表是否有交点。

                可以通过遍历两个链表找到各自的尾结点,再比较两个尾结点是否相等,如果相等则证明相交,不相等则不相交(链表的相交和直线相交不一样,直线相交后朝各自的方向继续延伸,呈X形,而链表相交后由于交点的next一样,是往同一方向延伸的,呈Y形)

        如果相交,找交点。

                从各自的头开始遍历,计算出各自长度(假设为longlen、shortlen),区分出哪个长哪个短,再计算出长度差值的绝对值 num = abs(longlen-shortlen)。各自再次从头开始遍历,长链表先走num步,然后长短链表一起走,直到找到交点。(longlen-num=shortlen,长链表先走num步,这样当短链表开始走的时候长短链表会同时到达尾结点,同理也会同时到达交点)

ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {

    if (headA == NULL || headB == NULL) {
        return NULL;
    }

    //分别从两个头开始遍历,计算各自的路径长
    ListNode* cur1 = headA;
    ListNode* cur2 = headB;
    int len1 = 0;
    int len2 = 0;
    while (cur1->next) {
        cur1 = cur1->next;
        len1++;
    }
    while (cur2->next) {
        cur2 = cur2->next;
        len2++;
    }
    //尾结点不相等则不相交
    if (cur1 != cur2) {
        return NULL;
    }
    //找出更大的
    int lenlong = 0;
    int lenshort = 0;
    ListNode* longlist = NULL;
    ListNode* shortlist = NULL;
    if (len1 > len2) {
        longlist = headA;
        shortlist = headB;
    }
    else {
        longlist = headB;
        shortlist = headA;
    }
    //计算差值
    int num = abs(len1 - len2);
    //长的先走num步
    while (num--) {
        longlist = longlist->next;
    }
    //一起走
    while (longlist != shortlist) {
        longlist = longlist->next;
        shortlist = shortlist->next;
    }

    return longlist;
}

二、

        求入环点会用到找交点的知识

        使用快慢指针可以判断是否有环

        设快慢指针相遇点为meet,已知环形链表的头head1,把meet->next设为另一个头head2,如此我们就可以把一个环形链表拆成两个链表(head1~meet,head2~meet),这两个链表的交点就是入环点

        

ListNode* detectCycle(ListNode* head) {
    //快慢指针遍历单链表,找到相遇点meet
    //计算head到meet的距离len1,以及环的长度len2
    //把head - meet和meet->next - meet各自看做一个链表
    //接下来使用找两个交点的方式求解
    ListNode* fast = head;
    ListNode* slow = head;

    while (fast && fast->next) {
        fast = fast->next->next;
        slow = slow->next;

        if (slow == fast) {

            int len1 = 0, len2 = 0;

            //创建一个cur遍历,求len1和len2
            ListNode* cur = head;
            while (cur != slow) {
                len1++;
                cur = cur->next;
            }
            cur = slow->next;
            while (cur != slow) {
                len2++;
                cur = cur->next;
            }

            //定义长短链表,默认从head开始长从meet->next开始短
            ListNode* longlist = head;
            ListNode* meet = slow;
            ListNode* shortlist = meet->next;
            if (len1 < len2) {
                longlist = meet->next;
                shortlist = head;
            }

            int gap = abs(len1 - len2);

            //长的先走
            while (gap--) {
                longlist = longlist->next;
            }

            //一起走,相遇点则为入环点
            while (longlist != shortlist) {
                longlist = longlist->next;
                shortlist = shortlist->next;
            }

            return longlist;

        }
    }

    return NULL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值