142. 环形链表 II
兔子赶上了乌龟说明有环:
- 首先,链表有环的话只能有一个环,就是上图的形状,因为每个节点只有一个next节点。
- 兔子一次走m步,乌龟一次走n步。当兔子追上乌龟就是 (m-n)=k*环的长度,当m-n越大,就走的环数k越大,复杂度越高。不管m n为多少,这个算法正确性都是可以保证的
由于 环长=fast-slow fast=2*slow 所以环长=slow
y+z=slow,x+y=slow;所以z=x;
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast=head,*slow=head;
if(head==NULL) return NULL;
while(fast!=NULL&&fast->next!=NULL){
fast=fast->next->next;
slow=slow->next;
if(fast==slow){
slow=head;
while(slow!=fast) slow=slow->next,fast=fast->next;
return slow;
}
}
return NULL;
}
};
287. 寻找重复数
- 我刚开始看的时候有个疑惑,假如nums[slow]=slow,nums[fast]=nums[fast]怎么办,都不走了,而且此时slow!=fast就更不可能相等了,怎么办。
我真的人傻了啊。
- 首先假如真的nums[slow]=slow,slow不能前行了,fast也不能前行了,他们一定会再在一个地方停留,不会出现 slow!=fast的情况。
- 其次首先 nums[slow]=slow了,说明还有一个其他的位置比如k把,nums[k]=slow,否则这个slow是从0怎么到达slow的(我们称x->nums[x]->nums[nums[x]]->nums[nums[nums[x]]]这一过程为到达),而且slow!=0,因为不存在nums[0]=0,vector里面数字都是1-n。
好了,言归正传。nums[k]=slow,nums[slow]=slow。早晚fast会等于slow。
这不就回到了普通情况吗。
- 我好傻啊,以为这一步就完事了,返回slow。。slow只是环中的某个相遇点而已,要继续找到环的入口。
class Solution {
public:
int findDuplicate(vector<int>& a) {
int fast=0,slow=0;
do{
slow=a[slow],fast=a[a[fast]];
}while(slow!=fast);
slow=0;
while(slow!=fast) slow=a[slow],fast=a[fast];//找到环的入口
return slow;
}
};
876. 链表的中间结点(fast== NULL||fast->next==NULL 则 slow是中间节点)
- 奇数链表
- 偶数链表
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode *fast=head,*slow=head;
while(fast!=NULL&&fast->next!=NULL){
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
};
234. 回文链表
题目
回文链表肯定要找到中间节点,由上一题返回中间节点,所以我们想这个用快慢指针做。
由于为了不让next反向次数多了一个,导致奇数偶数要分类讨论。我们让慢指针再慢走一步,也就是while里面做判断,fast== NULL||fast->next==NULL就break,不让slow继续走了,就达成了目的。
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head==NULL||head->next==NULL) return true;//链表只有一个节点时
ListNode *slow=head,*fast=head;
ListNode *tmpnex=slow->next,*nexnex=NULL;
while(1){
fast=fast->next->next;
if(fast==NULL||fast->next==NULL) break;
nexnex=tmpnex->next;
tmpnex->next=slow,slow=tmpnex,tmpnex=nexnex;
}
head->next=NULL;//链表只有两个节点时,slow还是头节点,指针指向不变,slow->next就是tmpnex了..
if(fast!=NULL) tmpnex=tmpnex->next;//不可以写成fast->next!=NULL,fast=NULL时会空值异常.
while(slow!=NULL){
if(slow->val!=tmpnex->val) return false;
slow=slow->next,tmpnex=tmpnex->next;
}
return true;
}
};