刷代码随想录09--链表

环形链表II

142. 环形链表 II - 力扣(LeetCode)

没思路,甚至想先看一下能不能算出size,但是应该会直接死循环

法一:

遍历一个元素就存一个在vector里,并且每次都查询这个元素的指针和vecor里的历史指针有没有相等的

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution { // 也是指针相等
public:
    ListNode* detectCycle(ListNode* head) {
        vector<ListNode*> num;
        if (head == nullptr) {
            return nullptr;
        }
        ListNode* p = head;
        while (p != nullptr) { 
            num.push_back(p);
            for (ListNode* q : num) {//vector遍历
                if(p->next == q){//
                    return q;
                }
            }
            p = p->next;
        }
        return nullptr;
    }
};

法二:强数学推理

挺抽象的

fast和slow速度比2:1,时间相同,距离【x+y+n(y+z)】 : (x+y)

为什么是(x+y)呢,即为什么slow一定不会转1圈以上再相遇呢:【这很重要,因为n不是fast和slow的路程差,而是实际路程,因为这是在算比例】

-->【slow在环入口时,fast在环入口任意位置(不考虑就在环入口这个特殊情况),这里假设在位置k处。

可以自己画一个圈,在此刻,相当于fast追slow,从物理意义将,fast位移x1是个负值,x1 = -k;slow的位移x2 = 0 ;

若slow走了一圈即x1=n; x2 = 2n-k;

可以自己画一个x-t图,会发现会相交的。】

得:2(x+y ) = x+y+n(y+z)

x = (n-1)(y+z)+z,结合上图,即一个指针从head走,一个从fast和slow相交点走,相同速度总会相遇。

代码:注意while(p!=nullptr && p->next!=nullptr),因为p是快的指针,所以while里不用考虑q,涉及到p->next->next,所以涉及p->next;

链表只有头结点的情况没有考虑,所以p!=nullptr,避免p->next出现问题(可以考虑用虚拟指针)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution { // 也是指针相等
public:
    ListNode* detectCycle(ListNode* head) {
        if(head == nullptr){
            return nullptr;
        }
        ListNode *p,*q;//p快
        p = q =head;
        int tag = 0;
        while(p!=nullptr && p->next!=nullptr){//p!=nullptr && p->next!=nullptr
            p=p->next->next;
            q = q->next;
            if(p==q){
                tag = 1;
                break;
            }
        }
        if(tag == 0){
            return nullptr;
        }
        p = head;
        while(p!=q){
            p = p->next;
            q = q->next;
        }
        return p;

    }
};

快慢指针(双指针)用法总结

翻转链表

删除链表的倒数第N个节点

链表相交

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值