Leecode.287 寻找重复数
看的时候想了半天,leecode官方有带动图的解释。但可以发现,快慢指针可以很高效地求解带环的问题,其核心思想就是快指针永远是慢指针的两倍,因此他们一定可以在一个有环的地方交汇。
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int fast = 0, slow = 0;
do{
fast = nums[nums[fast]];
slow = nums[slow];
}while(nums[fast] != nums[slow]);
slow = 0;
while(slow != fast){
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
};
Leecode.141 环形链表
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head || !head -> next)return false;
ListNode* fast = head -> next, *slow = head;
bool judge = true;
while(fast && fast -> next){
if(fast == slow)return true;
fast = fast ->next -> next;
slow = slow ->next;
}
return false;
}
};
Leecode. 142 环形链表
这个题和寻找重复数在做法上有那么一点点像,但是没有寻找重复数的定理基础。
主要实现是基于:
- 当快慢指针相遇的时候,慢指针走过了a+b(a是环外距离,b是环内距离), 快指针走过了 2(a + b),因此慢指针再走(a + b)就可以走到当前位置,又由于b是环内的距离,则a是到达环口的距离,因此再走过a即可找到入环处。
- 如何评估走过了a?可以用快指针来对照。将快指针放到头结点,那么快指针走过a步也会走到入环口,即会跟慢指针相遇。因此在二者相等的时候即为入环处。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
// if(!head || !head->next)return nullptr; 无法防止只有两个数并pos = -1,即无环的情况
ListNode *fast = head, *slow = head;
while(fast && fast -> next){// while(fast->next && fast->next->next) 根据情况转换
fast = fast -> next -> next;
slow = slow -> next;
if(fast == slow)break;
}
if(!fast || !fast->next)return nullptr;//需要将这个判断加在下面
fast = head;
while(1){
if(fast == slow)return fast;
fast = fast -> next;
slow = slow -> next;
}
return nullptr;
}
};