LeetCode | Linked List Cycle I,II

100 篇文章 0 订阅
13 篇文章 0 订阅

Given a linked list, determine if it has a cycle in it.

Follow up: Can you solve it without using extra space?

这道题想做出来不难,关键是快慢指针这种一般想不到。。
一般想到的是拿哈希存储已经经过的pointer
这种空间复杂度O(n)
快慢指针这个很巧妙,设置两个指针fast和slow,fast一次走两步,slow一次走一步,这样二者如果能够相遇,那么表示有环


class Solution {
public:
    bool hasCycle(ListNode *head) {
        //这种想法是错误的,因为有可能在中间的地方出现换,那就gg了
        // //有环应当能遍历到自己
        // ListNode* temp=head;

        // while(temp!=NULL){
        //     temp=temp->next;
        //     if(temp==head) return true;
        // }

        // //于是想到记录每一个出现过的pointer
        // unordered_map<ListNode*,bool> visited;
        // ListNode* temp=head;
        // while(temp!=NULL){
        //     //首先判断它是否在map里
        //     if(visited.find(temp)!=visited.end()){
        //         return true;
        //     }
        //     else{
        //         visited[temp]=true;
        //         temp=temp->next;
        //     }
        // }

        //上面的办法时间复杂度O(n^2) 空间复杂度O(n)
        ListNode* slow=head,*fast=head;
        while(fast && fast->next){
            slow=slow->next;
            fast=fast->next->next;
            if(slow==fast) return true;
        }


        return false;
    }
};

Linked List Cycle II所将的是要我们找出这个入口点

当fast与slow相遇时,slow肯定没有遍历完链表,而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,fast走了2s步,设环长为r,则
2s=s+nr
s=nr
设整个链表长L,环入口点与相遇点距离为a,起点到环入口点的距离为x,则
x+a=nr=(n-1)r+L-x
x=(n-1)r+(L-x-a)
L-x-a为相遇点到环入口点的距离
由此可知,从相遇点出发和从起点出发的两个指针,它们一定会在入口的地方相遇
和这篇文章考虑的类似
http://blog.sina.com.cn/s/blog_6f611c300101fs1l.html
不过他没有考虑nr的情况,所以显得有点不严谨,不过做法是完全一样的。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {

        //我忽略了一个严重的问题,就是在二者相遇之前,fast有可能已经在环内走了n圈了....
        // ListNode* slow=head,*fast=head;
        // int fast_count=0;
        // while(fast && fast->next){
        //     slow=slow->next;
        //     fast=fast->next->next;
        //     fast_count+=2;
        //     if(slow==fast) break;
        // }

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

        // //直到这里,fast_count和slow_count分别记录的走的步数
        // //让fast停下,slow继续走
        // int circle_count=0;
        // do{
        //     slow=slow->next;
        //     circle_count++;
        // }while(slow!=fast);

        // //一开始fast_count比slow_count多走了一圈,然后除去这个周长
        // //就是不在环里的部分
        // int k=fast_count-circle_count;
        // slow=head;
        // for(int i=1;i<k;i++,slow=slow->next);


        ListNode* slow=head,*fast=head;
        while(fast && fast->next){
            slow=slow->next;
            fast=fast->next->next;
            if(slow==fast){
                //另一节点从起点开始出发
                ListNode* slow2=head;
                while(slow!=slow2){
                    slow=slow->next;
                    slow2=slow2->next;
                }
                //二者会在入口相遇
                return slow2;
            }
        }

        return NULL;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值