大家好,这里是小编的博客频道
小编的博客:就爱学编程
很高兴在
CSDN
这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!
目录
- 1.环形链表
- (1)题目描述
- (2)解题思路
- (3)复杂度分析
- 2.环形链表2
- (1)题目描述
- (2)解题思路
- (3)复杂度分析
- 快乐的时光总是短暂,咱们下篇博文再见啦!!!如果小编的文章会对你有帮助的话不要忘了,记得给小编点赞、收藏支持一下,在此非常感谢!!!
废话不多说,我们直接看题。
1.环形链表
(1)题目描述
(2)解题思路
快慢指针
但要注意:最好使得快指针
fast
一次走两步,慢指针slow
一次走一步使得两指针的速度之差为1
。这样就不可能会出现有环不相交的问题。
代码实现:
bool hasCycle(struct ListNode *head) {//快慢指针看是否会相遇,但最好快指针一次走两步,慢指针一次走一步,就不会出现有环却不相遇的情况struct ListNode* fast = head, * slow = head;if(head == NULL) return false;while(fast && fast->next){fast = fast->next->next;slow = slow->next;if(fast == slow){return true;}}return false;
}
(3)复杂度分析
- 时间复杂度:
O(N)
,其中 N 是链表中的节点数。
- 空间复杂度:
O(1)
。我们只使用了两个指针的额外空间。
2.环形链表2
(1)题目描述
(2)解题思路
思路一:先找到相交点再把相交的点next指针指向空,这样就转变成了头指针
head
和·相遇点的next
指针找交点问题。
代码实现:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {if (headA == NULL || headB == NULL) {return NULL;}struct ListNode *p1 = headA, *p2 = headB;while (p1 != p2) {p1 = p1 == NULL ? headB : p1->next;p2 = p2 == NULL ? headA : p2->next;}return p1;
}struct ListNode *detectCycle(struct ListNode *head) {if (head == NULL) return NULL;struct ListNode* fast = head, * slow = head;while (fast && fast->next) {//先走,防止因为头指针相等fast = fast->next->next;slow = slow->next;if (fast == slow) {struct ListNode* ptr = fast->next;fast->next = NULL;return getIntersectionNode(ptr, head);}}return NULL;
}
思路二:借助定理——两个快慢指针他们相交于环内一位置,而一指针从该位置开始走,同时另一从链表的头结点开始走,它们最终会第一次相交于环开始的那个节点。(怎么得到这个定理的一定要掌握,因为HR问到会问这个)
定理推导:
- 我们使用两个指针,
fast
与slow
。它们起始都位于链表的头部。随后,slow
指针每次向后移动一个位置,而fast
指针向后移动两个位置。如果链表中存在环,则fast
指针最终将再次与slow
指针在环中相遇。- 设链表中环外部分的长度为
a
。slow
指针进入环后,又走了b
的距离与fast
相遇。此时,fast
指针已经走完了环的n
圈,因此它走过的总距离为a + n(b + c) + b = a + (n + 1)b + nc
。- 根据题意,任意时刻,fast 指针走过的距离都为 slow 指针的
2
倍。因此,我们有a + (n + 1)b + nc = 2(a + b)⟹a = c + (n−1)(b + c)
- 有了
a = c + (n−1)(b + c)
的等量关系,我们会发现:从相遇点到入环点的距离加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离。- 因此,当发现
slow
与fast
相遇时,我们再额外使用一个指针ptr
。起始,它指向链表头部;随后,它和slow
每次向后移动一个位置。最终,它们会在入环点相遇。
代码实现:
struct ListNode *detectCycle(struct ListNode *head) {//这题要做出就一定要推出一个定理:两个快慢指针他们相交于环内一位置,而一指针从该位置开始走,同时另一从链表的头结点开始走,它们最终会第一次相交于环开始的那个节点。(怎么得到这个定理的一定要掌握,因为HR问到会问这个)struct ListNode* fast = head, * slow = head;if (head == NULL) return NULL;while (fast && fast->next) {//先走,防止因为头指针相等fast = fast->next->next;slow = slow->next;if (fast == slow) {struct ListNode* ptr = head;while(ptr != slow){ptr = ptr->next;slow = slow->next;}return ptr;}}return NULL;
}