力扣142. 环形链表 II(快慢指针加F=b、哈希)
https://leetcode-cn.com/problems/linked-list-cycle-ii/
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。
进阶:
你是否可以不用额外空间解决此题?
一、哈希map
保存已经访问过的节点,我们可以遍历整个列表并返回第一个出现重复的节点
复杂度分析
-
时间复杂度:O(n),运行时间跟节点数目成线性关系
-
空间复杂度:O(n),所需空间与节点数目也是线性关系的
class Solution
{
public:
ListNode *detectCycle(ListNode *head)
{
if (head == nullptr)return nullptr;
map<ListNode*, int>mp;
ListNode* cur = head;
while (cur != nullptr)
{
mp[cur]++;
if (mp[cur] == 2)return cur;
cur = cur->next;
}
return nullptr;
}
};
二、快慢指针和F=b
复杂度分析
-
时间复杂度:O(n),与节点数成线性关系的时间
-
空间复杂度:O(1),常数级别的额外空间
1、慢指针一步、快指针两步
如果存在环,则快慢指针相遇重合
如果不存在环,则快指针无法继续往前移动
2、头结点到循环开始点的距离 等于 相遇点到循环开始点的距离
#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution
{
public:
ListNode *detectCycle(ListNode *head)
{
if (head == nullptr)return nullptr;
//快慢指针找相遇点
ListNode* low = head;
ListNode* fast = head;
do
{
if (low->next == nullptr || fast->next == nullptr || fast->next->next == nullptr)return nullptr;
low = low->next;
fast = fast->next->next;
} while (low != fast);
//数学可是头结点到循环开始点的距离 等于 相遇点到循环开始点的距离
ListNode* converge = low;
ListNode* cur = head;
while (cur != converge)
{
cur = cur->next;
converge = converge->next;
}
return cur;
}
};
int main()
{
ListNode head[5] = { -10,-3,-1,0,5 };
head[0].next = &head[1];
head[1].next = &head[2];
head[2].next = &head[3];
head[3].next = &head[4];
head[4].next = &head[1];
Solution s;
auto result = s.detectCycle(head);
return 0;
}