环形链表Ⅱ

题目:见下图

答案:见下图

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* detectCycle(struct ListNode* head) {
    ListNode* fast = head;
    ListNode* slow = head;

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

        if (fast == slow) {
            break;
        }
    }

    if (fast==NULL || fast->next==NULL) {
        return NULL;
    }

    ListNode* meet = head;

    while (fast!=meet) {
        fast = fast->next;
        meet = meet->next;
    }

    return meet;
}

解析:

(1)使用快慢指针找出在链表环中的相交点

采用快慢指针,快慢二倍指针在环形链表中是会相遇,具体可见我的下一篇博客,找出交点再利用head到环形链表的头结点的关系即可进行求解

    ListNode* fast = head;
    ListNode* slow = head;

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

        if (fast == slow) {
            break;
        }
    }

(2)判断链表是否是环形链表

倘若链表不为环形链表那么走的快的指针便会走到末尾的空指针,反之则为环形链表,环形链表中的指针会在链表中一直走一直循环,不会出现NULL的状况

   if (fast==NULL || fast->next==NULL) {
        return NULL;
    }

(3)找出相遇点

假设链表的总长度为C,头链表到环形链表的交点的距离为L,两个结点相交,慢指针走到路程为X

那么有两种情况

1.head到环形链表的交点的长度小于环形链表的长度,

此时有短指针的路程为(L+X)

长指针的路程为(L+C+X)

由于长指针的路程是短指针的二倍,那么有2(L+X)=(L+X+C)

解的L=C-X,此时我们可以定义一个meet指针=head,让meet指针和fast指针走相同步,那么其相遇点即为环形链表的头节点

2.接下来我们开始讨论第二种情况,即head到环形链表的交点长度大于环形链表的长度,此时快慢指针相遇时快指针已经在环形链表中走了好多圈我们记为N圈,同理

此时有短指针的路程为(L+X)

长指针的路程为(L+N*C+X)

由于长指针的路程是短指针的二倍,那么有2(L+X)=(L+X+N*C)

化简L+X=N*C

L+X=(N-1)*C+C,那么(N-1)*C我们可以认为长指针在链表中绕了整整(N-1)圈,那么我们可以在这里再次化简为L=C-X+(N-1)*C,这里我们可以想象一下有若干个长度为C的环形链表其为(N-1)个,对应快指针的圈数,将其累加起来,定义一个meet指针=head,让meet指针和fast指针走相同步,那么其相遇点即为环形链表的头节点

    ListNode* meet = head;

    while (fast!=meet) {
        fast = fast->next;
        meet = meet->next;
    }

    return meet;

到这里我们解题完毕

如果对您有帮助的话点一个免费的赞和收藏叭!

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值