Leetcode 142:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
解题思路:
设置两个指针,一个快(fp), 一个慢(sp)。fp每次走两步,速度是
2v
,sp每次走一步,速度是
v
。当两次指针第一次相遇时,fp比sp多走了一个circle的距离,设循环之前的长度是
快指针:
2v×s1=l+c+c1
慢指针:
v×s1=l+c1
化简去掉
v
和
c−c1=l
此等式说明慢指针到圆环起点的距离恰好等于链表起点到圆环起点的距离。如下图:
然后一个指针回到起点,另一个从相遇点出发,当两个指针再次相遇时,相遇点便是圆环的起点:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow=head;
struct ListNode* fast=head;
while(slow!=NULL && fast!=NULL){
fast=fast->next;
slow=slow->next;
if(fast!=NULL) fast=fast->next;
if(fast==slow) break;
}
if(fast==NULL) return NULL;
fast=head;
while(fast!=slow){
fast=fast->next;
slow=slow->next;
}
return fast;
}
Leetcode 287
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:
- You must not modify the array (assume the array is read only).
- You must use only constant, O(1) extra space.
- Your runtime complexity should be less than O(n2).
- There is only one duplicate number in the array, but it could be repeated more than once.
解题思路
之所以将这两个题放在一起,是因为这第二个题可以看成以第一个题的变种,问题的关键是怎么将第二题转换成第一题,举个例子
4 | 5 | 6 | 1 | 3 | 2 | 5 | 7 |
---|
从位置0开始,
- 位置0的值是4,
- 位置4的值是3,
- 位置3的值是1,
- 位置1的值是5,
- 位置5的值是2,
- 位置2的值是6,
- 位置6的值是5,
- 位置5的值是2,
此时便形成了一个环
4->3->1->(5->2->6)->(5->2->6)…
和142题一样,圆环的起点便是重复的那个值
class Solution {
public:
int findDuplicate(vector<int>& nums) {
if(nums.size()>1){
int slow=nums[0];
int fast=nums[nums[0]];
while(slow!=fast){
slow=nums[slow];
fast=nums[nums[fast]];
}
fast=0;
while(slow!=fast){
slow=nums[slow];
fast=nums[fast];
}
return slow;
}
return -1;
}
};