带环链表之灵魂三问!
今天舍友二狗子又去面试了,回来就问我们算法问题,看来对于ios开发来说算法是一个大难题啊!
今天是什么呢?当然是带环链表的问题了。
这就让我想起了当初的带环链表三连问!现场慌的不行不行的。
一、判断链表是否有环
一句话解释:使用快慢指针,同时指向头节点,slow指针每次走一个节点,fast指针每次走两个节点,最终如果两个指针相遇,则表示有环!
二、找出环的入口
第一问很简单,第二问就有点难度了,哈哈!当初栽过跟头了,都是泪~
假设:快慢指针都从环的入口开始走,那么在慢指针跑一圈,快指针跑两圈的时候,两个指针肯定在入口处相遇;
那么:如果快慢指针从链表头开始走的话呢?当两个指针相遇的时候,就表示:快指针走的距离 = n个环的距离 + 慢指针走的距离,环的长度=相遇点和入口两段的距离,慢指针走的距离可以简化为:链表开头到环入口+环入口到相遇点的距离
结论:链表入口到环入口距离 = n个环的长度+慢指针到环入口距离,那么慢指针到环入口距离==链表入口到环入口距离,只要快指针指向链表入口,和慢指针同步移动,再次相遇的节点就是环的入口节点;(SUCCESS)
三、计算环的长度
这个是在第二步的基础上计算的,只要找到环的入口,走一遍就可以算出长度了!
四、代码实现
#include <stdio.h>
#include <stdlib.h>
struct Node{
int num;
struct Node *next;
};
void initList(struct Node *ListHead){
struct Node *node1 = malloc(sizeof(struct Node));
struct Node *node2 = malloc(sizeof(struct Node));
struct Node *node3 = malloc(sizeof(struct Node));
struct Node *node4 = malloc(sizeof(struct Node));
struct Node *node5 = malloc(sizeof(struct Node));
struct Node *node6 = malloc(sizeof(struct Node));
struct Node *node7 = malloc(sizeof(struct Node));
struct Node *node8 = malloc(sizeof(struct Node));
struct Node *node9 = malloc(sizeof(struct Node));
struct Node *node10 = malloc(sizeof(struct Node));
struct Node *node11 = malloc(sizeof(struct Node));
struct Node *node12 = malloc(sizeof(struct Node));
ListHead->num = 0;
node1->num = 1;
node2->num = 2;
node3->num = 3;
node4->num = 4;
node5->num = 5;
node6->num = 6;
node7->num = 7;
node8->num = 8;
node9->num = 9;
node10->num = 10;
node11->num = 11;
node12->num = 12;
ListHead->next = node1;
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = node5;
node5->next = node6;
node6->next = node7;
node7->next = node8;
node8->next = node9;
node9->next = node10;
node10->next = node11;
node11->next = node12;
node12->next = node4;
printf("Set Address: %p, Value:%d \r\n", node4, node4->num);
}
int main(){
struct Node *ListHead = malloc(sizeof(struct Node));
// 0. 初始化链表
initList(ListHead);
// 1. 判断是否有环
struct Node *slow = ListHead->next;
struct Node *fast = ListHead->next->next;
for(;;){
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
printf("YES! slow=fast address: %p, Value: %d \r\n", slow, slow->num);
break;
}
}
// 2. 寻找环的入口
fast = ListHead;
for(;;){
slow = slow->next;
fast = fast->next;
if(slow == fast) break;
}
printf("Enter Address: %p, Value: %d \r\n", slow, slow->num);
// 3. 计算环的长度
int i = 0;
fast = slow->next;
for(i=1; fast!=slow; i++)
fast = fast->next;
printf("Length: %d\r\n", i);
return 0;
}
——2020-04-09——