当前位置: 首页> 健康> 养生 > 网站网站建设设计公司_品牌词优化_成人专业技能培训机构_百度极简网址

网站网站建设设计公司_品牌词优化_成人专业技能培训机构_百度极简网址

时间:2025/7/11 19:28:35来源:https://blog.csdn.net/huayimenghan/article/details/143808294 浏览次数:1次
网站网站建设设计公司_品牌词优化_成人专业技能培训机构_百度极简网址

LeetCode 热题 100_环形链表(25_141)

    • 题目描述:
    • 输入输出样例:
    • 题解:
      • 解题思路:
        • 思路一(哈希表):
        • 思路二(快慢指针):
      • 代码实现
        • 代码实现(思路一(哈希表)):
        • 代码实现(思路二(快慢指针)):

题目描述:

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

输入输出样例:

示例 1:
请添加图片描述

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:
请添加图片描述

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:
请添加图片描述

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。

题解:

解题思路:

思路一(哈希表):

1、使用一个哈希集合来存储遍历到的结点的地址。如果遍历到的结点不存在哈希集合中,则将该节点添加到哈希集合中。如果遍历到的结点已经存在哈希集合中则存在环,如果遍历整个链表结束则无环。

2、解题步骤
① 创建哈希集合用于进行环的判断。
② 遍历链表中的结点,如果遍历到的结点不存在哈希集合中,则将该节点添加到哈希集合中。如果遍历到的结点已经存在哈希集合中则存在环。
③ 遍历整个链表结束则无环。

3、复杂度分析:
① 时间复杂度:O(N),其中 N 是链表中的节点数。最坏情况下我们需要遍历每个节点一次(环可能在中间部分)。
② 空间复杂度:O(N),其中 N 是链表中的节点数。主要为哈希表的开销,最坏情况下我们需要将每个节点插入到哈希表中一次。

思路二(快慢指针):

1、使用快慢指针,快指针每次移动2步,慢指针每次移动1步。如果没有环,fast会先到达末尾nullptr。如果存在环的话,快指针与慢指针会在环中每次缩进一个单位的距离,最终快指针会追上慢指针,达到fast=slow的条件。

2、解题步骤
① 首先判断链表是否为空,第一个结点的next是否为空。
② 将slow指向首节点,fast指向首节点的next结点(防止一开始slow=fast的情况,且注意一个结点也可成环)。
③ 遍历单链表,slow指针每次移动一步,fast指针每次移动两步。
④ 如果fast到达链表的末尾则无环,如果最后fast==slow则存在环。

3、复杂度分析
① 时间复杂度:O(N),其中 N 是链表中的节点数。
当链表中不存在环时,快指针将先于慢指针到达链表尾部,为O(N/2)。
当链表中存在环时,每一轮移动后,快慢指针的距离将减小一。当慢指针移动到进入环的结点时,此时快指针已经在环上,快慢指针的最大距离为环的长度减一,所以。所以为O(N)。

② 空间复杂度:O(1)。我们只使用了两个指针的额外空间。

代码实现

代码实现(思路一(哈希表)):
bool hasCycle1(ListNode *head) {//mp用于存放没遍历过的结点地址unordered_set<ListNode*> mp;//如果遍历到的结点不存在哈希集合中,则将该节点添加到哈希集合中。如果遍历到的结点已经存在哈希集合中则存在环。while(head!=nullptr) {if(mp.count(head)){return true;}mp.insert(head);head=head->next;}return false;
}
代码实现(思路二(快慢指针)):
bool hasCycle2(ListNode *head) {//先排除特殊情况方便快慢指针的赋值 if(head==nullptr||head->next==nullptr){return false;}//注意初始时fast是slow后的一个结点(避免一开始相同的情况) ListNode *fast=head->next,*slow=head;//当slow==fast时存在环,如果fast到达末尾则不存在环 while(slow!=fast){if(fast==nullptr||fast->next==nullptr){return false;}fast=fast->next->next;slow=slow->next; } return true;
}

以思路二为例完成代码调试

#include<iostream>
#include<vector>
using namespace std;struct ListNode{int val;ListNode *next;ListNode(int x):val(x),next(nullptr){}
};//尾插法创建单链表 
ListNode* createList(const vector<int> &a){ListNode *head=nullptr,*tail=nullptr;for(const auto &val:a){ListNode *newNode=new ListNode(val);if(head==nullptr){head=newNode;tail=newNode;}else{tail->next=newNode;tail=newNode;}} return head;
}//将单链表改成环状链表(注意这里仅构造末尾存在环的情况)
ListNode* createCircularList(ListNode *head,int pos){if(pos==-1){return head;} ListNode *posNode=head;//找到环形的入口结点 while(pos){posNode=posNode->next;--pos;}//从入口结点到尾结点 ListNode *tail=posNode;while(tail->next!=nullptr){tail=tail->next;}//将尾节点的next指针指向入口节点形成环 tail->next=posNode;return head;
} //判断是否构成环形链表
bool hasCycle2(ListNode *head) {//先排除特殊情况方便快慢指针的赋值 if(head==nullptr||head->next==nullptr){return false;}//注意初始时fast是slow后的一个结点(避免一开始相同的情况) ListNode *fast=head->next,*slow=head;//当slow==fast时存在环,如果fast到达末尾则不存在环 while(slow!=fast){if(fast==nullptr||fast->next==nullptr){return false;}fast=fast->next->next;slow=slow->next; } return true;
}int main(){vector<int> a={1,2};int pos=0;//创建单链表 ListNode *head=createList(a);//将单链表形成环 ListNode *cir_head=createCircularList(head,pos);//判断是否存在环 if(hasCycle2(cir_head)){cout<<"It's a circular linked list";}else{cout<<"It's not a circular linked list";}return 0;
} 

LeetCode 热题 100_环形链表(25_141)原题链接

unordered_map和unordered_set对比及用法请点击此链接

ListNode(int x):val(x),next(nullptr){}解读请点击此链接

欢迎大家和我沟通交流(✿◠‿◠)

关键字:网站网站建设设计公司_品牌词优化_成人专业技能培训机构_百度极简网址

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: