leetcode 一些快慢指针题

142. 环形链表 II

题目
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
兔子赶上了乌龟说明有环:

  1. 首先,链表有环的话只能有一个环,就是上图的形状,因为每个节点只有一个next节点。
  2. 兔子一次走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. 寻找重复数

题目
在这里插入图片描述
在这里插入图片描述

  1. 我刚开始看的时候有个疑惑,假如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。
    这不就回到了普通情况吗。
  1. 我好傻啊,以为这一步就完事了,返回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是中间节点)

题目
在这里插入图片描述

  1. 奇数链表
    在这里插入图片描述
  2. 偶数链表
    在这里插入图片描述
    在这里插入图片描述
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;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值