力扣(LeetCode)142.环形链表二(Linked List Cycle two)


142. Linked List Cycle II


没看题解时,我想到的是配合141题的查找是否有环,如果有,再遍历每个元素。依据是:如果有一个环,将快慢指针设置在入环处,那么快慢指针下一个(或者N次)相遇必定也在入环处。于是开始写出来的是时间复杂度比较差的算法。

bool hasCycle(struct ListNode *head) {
    if(head == NULL)
        return false;
    struct ListNode *slow = head, *fast = head;
    int ret = 0;
    while(fast->next != NULL && fast->next->next != NULL  ) {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast){
            ret = 1;
            break;
        }
    }
    if(ret == 1)
        return true;
    return false;
}
struct ListNode *detectCycle(struct ListNode *head){
if(hasCycle(head) == 0)
        return NULL;
    struct ListNode *slow = head, *fast = head, *p = head;
    while (p){
        do{
            slow = slow->next;
            fast = fast->next->next;
        }while(slow != fast);
        if(slow == p){
            return p;
        }
        p = p->next;
        slow = p;
        fast = p;
    }
    return NULL;
}*/

看了题解后发现可以用数学知识来得到入口与环之间的关系,然后先是自己倒腾了一些,发现推出来的带一些余数并且不能抵消,再去看看题解,看到一句话,两指针在环内相遇时,慢指针环内走的距离必然不会超过一个环(当入环口恰好在头指针时,下一次相遇也在头指针,这种情况也可以算在上面),这个结论假设一下就出来了:如果慢指针走了一个环的距离,此时快指针就走了两个环的距离,那么就会相遇,如果慢指针走了超过了一个环的距离,快指针就和慢指针已经相遇过一次了,如果入环口不在头指针,那么相遇的点肯定在入环口与链表“最后一个结点”之间

struct ListNode *detectCycle(struct ListNode *head) {
    if(head == NULL)
        return NULL;
    struct ListNode *slow = head, *fast = head;
    int ret = 0;
    while(fast->next != NULL && fast->next->next != NULL  ) {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast){
            ret = 1;
            break;
        }
    }
    if(ret == 1){
        struct ListNode *third = head;
        while(slow != third){
            slow = slow->next;
            third = third->next;
        }
        return slow;
    }
        
    return NULL;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值