我是靠谱客的博主 聪慧路灯,这篇文章主要介绍环形链表C/C++数据结构什么是环?例题 141. 环形链表公式推导:环形链表二,现在分享给大家,希望可以做个参考。

目录

什么是环?

例题 141. 环形链表

公式推导:

环形链表二  142. 环形链表 II

方法一:

方法二:

什么是环?

类似这种,结点下一个指针又指向链表本身,这样若遍历链表的话则会变成死循环。

 特殊情况:自己也有可能成环

 环的特点:

有两个指针指向环的起点

判断是否有环

例题 141. 环形链表

使用快慢指针,进入了环就变成了追及相遇的问题

 

 思路:快指针一次走两步,慢指针一次走一步,当两个指针相遇时,即在链表中存在环

 问题:为什么是快指针一次走两步?慢指针一次走一步?

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool hasCycle(struct ListNode *head) { //判断空链表 if(!head){ return NULL; } struct ListNode *slow=head; struct ListNode *fast=head; //判断条件是什么? //如果两个指针相等则有一个环 //就把它当作一个正常数组想 //因为只有这样才能从循环中出去 //判断条件怎么想? while(fast&&fast->next)){ fast=fast->next->next; slow=slow->next; //要是环的话根本出不去 if(fast==slow){ return true; } } return false; }

公式推导:

假设链表中无环

快指针走的距离=2*慢指针走到距离

假设链表中有环

进环前的距离L,环的长度C,环的开始点至相遇点的距离X

 

慢指针走过的距离:L+X

快指针走过的距离:L+C*N+X

由此可以得出一个等式

L+X=N*C

L=(N-1)*C+C-X

意思是在入环前的长度==环的长度-(开始点至相遇点的距离)

也就是说: 蓝色部分=L

环形链表二

方法一:

本题首先需要找到相遇点,然后设立两个新的指针,两个指针从相遇点和起始点一起走,两个指针相遇的地方即为环形链表的起始点。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct ListNode *detectCycle(struct ListNode *head) { //L=C-X //创立快慢指针 struct ListNode *slow=head; struct ListNode *fast=head; //确保fast没有空指针 while(fast&&fast->next){ //两者一起向前走 slow=slow->next; fast=fast->next->next; //找到相遇 if(slow==fast){ struct ListNode *meet=slow; while(meet!=head){ //找到相遇点,两者一起走 meet=meet->next; head=head->next; } //相遇,返回环的起始点 return meet; } } return NULL; }

方法二:

使用相交链表的方式

先将链表从快慢指针的相遇点处断开

之后新建两个指针分别指向相遇点的下一位和原链表的头

利用相遇链表

相遇点即为起始点

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) { //想一想,极端情况 //首先应该判断这两个链表不为空 if(!headA||!headB) return NULL; //找到两个链表的最后一个节点 struct ListNode *lastA=headA; int numA=1; while(lastA->next) { lastA=lastA->next; numA++; } struct ListNode *lastB=headB; int numB=1; while(lastB->next) { lastB=lastB->next; numB++; } //判断是否相交 //这就是找最后一个节点的作用 if(lastA!=lastB) { return NULL; } //找到长度,找最长的那个 //不是说不能倒着走吗?难道是要它倒叙? //理解错了理解错了 struct ListNode *lenglist=headA; struct ListNode *shortlist=headB; if(numA<numB) { lenglist=headB; shortlist=headA; } //最长的先走 int distance=abs(numA-numB); while(distance--) { lenglist=lenglist->next; } //两个一起走 while(lenglist!=shortlist) { lenglist=lenglist->next; shortlist=shortlist->next; } //走到不相等时分开,返回相交的节点 return lenglist; } struct ListNode *detectCycle(struct ListNode *head) { //L=C-X //创立快慢指针 struct ListNode *slow=head; struct ListNode *fast=head; //确保fast没有空指针 while(fast&&fast->next){ //两者一起向前走 slow=slow->next; fast=fast->next->next; //找到相遇 if(slow==fast){ struct ListNode *meet=slow; struct ListNode*next=meet->next; struct ListNode*walk=meet->next; meet->next=NULL; struct ListNode *newNode=getIntersectionNode(head,walk); meet->next=next; return newNode; } } return NULL; }

最后

以上就是聪慧路灯最近收集整理的关于环形链表C/C++数据结构什么是环?例题 141. 环形链表公式推导:环形链表二的全部内容,更多相关环形链表C/C++数据结构什么是环?例题 141.内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部