题意分析
- 这个题目是NC3的弱化版,这个题目不需要我们求出环的入口结点,只需要我们判断是否存在环就可以。
思路分析
- 所以我们可以按照NC3那题的思路来写。
思路一 哈希处理
我们首先将所有的结点存入一个哈希表里面,然后我们需要遍历整个链表,如果存在相同的节点说明存在环,返回true即可。
代码如下
- 需要对整个链表进行遍历,时间复杂度为O(n)
- 用哈希方法存储整个链表的所有的结点的情况,空间复杂度为O(n)
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool hasCycle(ListNode *head) { map<ListNode*,int> mp; // 定义一个哈希表存储结点指针 while(head){ // 不断遍历结点 if(mp[head]){ //如果这个结点出现过 return true; } // 如果没有出现过,那么标记为1,表示出现过了 mp[head]=1; head=head->next; } return false; } };
解法二 数学
我们发现,题目特地指明了需要我们使用空间复杂度为O(1)的算法进行求解。所以我们可以接着NC3 中的数学的思路来进行求解。这个代码更加简洁,但是思维含量更高。空间复杂度更低。具体可以看下面的图。
代码
- 我们只需要判断是否存在结点,所以当fast指针和slow指针相遇的时候就可以直接停止,时间复杂度为O(直链的长度+环的长度^2)
- 需要存储整个链表,空间复杂度O(n)
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool hasCycle(ListNode *head) { ListNode* slow = head; // 定义两个结点指针,fast结点的速度快于slow ListNode* fast = head; while(fast!=NULL&&fast->next!=NULL){ // 不断让这两个指针移动 fast=fast->next->next; slow=slow->next; if(slow==fast){ // 如果存在移动到同一个节点指针,那么说明存在环 return true; } } return false; } };