文章目录
- 题目
- 题目链接
- 题目要求
- 解题思路
- 方法一:哈希表
- 方法二:双指针
- 进阶思考
- 快指针一次走三步
- 进阶问题(入口点)
- 题目链接
- 题目要求
- 问题思路
- 总结
题目
题目链接
环形链表
题目要求
解题思路
显而易见的是,单纯的遍历循环是肯定不行的,既然是循环,关键就是要找到重复的地址,用值判断不行的,可能有重复的值。
方法一:哈希表
1,用哈希表储存节点指针的值,找到重复的则返回TRUE。
class Solution {
public:bool HasCycle(ListNode *head) {unordered_set<ListNode*> hashtable; //哈希表while (head != nullptr) {if (hashtable.count(head)) {//如果当前节点已经有存储,则说明有重复return true;}//插入节点hashtable.insert(head);head = head->next;}return false;}
};
方法二:双指针
1,即使不会哈希表也没关系,用常见的快慢指针也可以解题。
2,不是循环链表:快指针会到达空节点,直接返回false即可。
3, 是循环链表:快指针先进入环中,变成追击问题,画图如下。
4,追击过程中,距离变化:(快指针一次两步,慢指针一次一步)
代码实现:
bool hasCycle(struct ListNode *head) {if(head == NULL||head->next == NULL) return false;struct ListNode *slow = head;struct ListNode *fast = head->next;while(fast!=NULL && fast->next!=NULL){slow = slow->next;fast = fast->next->next;if (fast == slow){return true;}}return false;
}
进阶思考
快指针一次走三步
1,快指针相当于每次追击两步,要分情况讨论初始距离的情况。
如下:
2,可以看出,当N为偶数时是可以追上的,当N为奇数则分情况。
- 距离为-1时,实际距离是C-1(C为环的长度)
如图:
3,可以看出,C为奇数时可以达成,为偶数则不行。
4,更多的步数则是以此类推。
进阶问题(入口点)
题目链接
环形链表入口
题目要求
问题思路
1,显而易见,第一个重复的节点就是入口节点,可以用哈希表判断,直接返回第一个节点。
代码:
class Solution {
public:ListNode *detectCycle(ListNode *head) {unordered_set<ListNode *> visited;while (head != nullptr) {if (visited.count(head)) {return head;}visited.insert(head);head = head->next;}return nullptr;}
};
2,快慢指针,经过前面的推论我们可以进一步推导得到如下:
3,如此可知,M为1的时候, 一个指针从相遇点走,一个从起点走,最终在入口点相遇。
代码实现:
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode *slow = head, *fast = head;while (fast != nullptr) {slow = slow->next;if (fast->next == nullptr) {return nullptr;}fast = fast->next->next;if (fast == slow) {ListNode *ptr = head;while (ptr != slow) {ptr = ptr->next;slow = slow->next;}return ptr;}}return nullptr;}
};
总结
做这种题需要假设举例,一定的数学推导,从例子中找出其中的普遍规律,才能快速解题。