1.哈希表解法
首先这题要我们找链表的环入口结点,最常规易懂的解法就是遍历整个链表结点,然后用哈希表来存储已访问过的结点,最后进行对比。 若该结点已存在哈希表中,则代表该结点是我们要找的环形链表的入口结点(找到第一个已经存在过的结点就是入口结点-可以验证);否则把结点添加到哈希表中,继续往下遍历。
时间复杂度
O
(
n
)
O(n)
O(n) 空间复杂度
O
(
n
)
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) {
//不管是快指针还是慢指针,进环之后都会开始在环中开始循环且遍历每个值,开始遍历的那个的最小值就是入口。
//找出三个遍历了两次的值,最小的值即可
ListNode* p=pHead;
unordered_set<ListNode*> st; //定义一个hashset
while(p->next!=NULL and p!=NULL){
if(st.count(p))
return p;
st.insert(p);
p=p->next;
}
return nullptr;
}
};
2.快慢指针数学公式计算法
这个方法我没有想到,利用解方程得出两者的数学关系。
这里参考其他人写的题解。
时间复杂度
O
(
n
)
O(n)
O(n),空间复杂度
O
(
1
)
O(1)
O(1)
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
ListNode *fast = pHead, *slow = pHead; // 快慢指针一开始都指向头
while(fast){
slow = slow->next; // 慢指针走一步
if(fast->next == nullptr) return nullptr; // 若快指针的下一步不能走,则说明两指针不会相遇
fast = fast->next->next; // 快指针向后走两步
if(fast == slow){ // 找到相交节点, 此时慢指针已经走了nb步
fast = pHead; // 快指针重新移动到头
while(fast != slow){ // 直到两指针相遇位置,每次向后走一步
fast = fast->next;
slow = slow->next;
}
return fast; // 找到入口节点,直接返回
}
}
return nullptr;
}
};