题意分析
- 这个题目给我们一个经过特殊处理的链表,这个链表分为两段,每一段包含一个链表的非环的部分和成环的部分。大多数人可能一开始看样例的时候会感觉不是很理解。其实你就只要知道它给你一个链表,这个链表中如果成环的话就说明这个链表里面存在相同的结点。也就是转化为问你给出一个链表,需要你判断这个链表里面是否存在相同的结点。返回这个相同的结点就行了。如果不存在环,那么就返回一个空指针。
- 样例可以结合这个图进行理解
- 前置知识,这个题目我们可以使用哈希算法进行处理,我们可以一边遍历整个链表,一边将所有的结点进行哈希处理。对于C++,有一个实现好的STL容器就是map,我们第一种写法就是利用这个来实现的。
思路分析
解法一 哈希
- 我们知道,既然要寻找两个相同的结点,那么我们就可以将这些结点存入哈希函数里面,我们遍历整个链表,如果当前这个结点已经不是初始的值,那么我们就可以判断这个就是一个环的入口。
- 代码如下
- 最坏的情况就是遍历整个链表,所以时间复杂度为O(n),
- 用哈希方法存储整个链表的所有的结点,空间复杂度为O(n)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
map<ListNode*,int> mp; // STL中的map进行哈希,初始的时候所有的哈希值都是0
while(pHead){ //遍历整个链表
if(mp[pHead]){ //如果这个结点指针的哈希值不是0,那么说明之前出现过
return pHead;
}
// 走到这一步说明这个是第一次出现的,标记这个哈希值为1
mp[pHead]=1;
pHead=pHead->next;
}
// 如果不存在的情况记得要返回一个空指针
return NULL;
}
};解法二 数学法
- 第二种方法是题解区看到的觉得比较新奇的解法。这种解法需要我们进行结合几何图形进行理解。首先,我们来看一下下面的图。
- 代码如下
- 假设在环上slow指针只能靠近fast指针一个位置,那么时间复杂度就是O(不成环的长度+成环的长度^2)
- 由于我们存储整个链表的所有的结点,所有空间复杂度为O(n)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
ListNode* slow = pHead; // 定义两个指针
ListNode* fast = pHead;
while(fast!=NULL&&fast->next!=NULL){
fast=fast->next->next; //fast指针走两步
slow=slow->next; // slow指针走一步
if(slow==fast){ //找到了相遇点
while(pHead!=slow){ //不断往前走
pHead=pHead->next;
slow=slow->next;
}
return pHead;
}
}
return NULL;
}
};
京公网安备 11010502036488号