简单链表求环算法问题【C++】

方法一:使用用C++的set库

遍历链表逐一装入set集合,当出现一个结点已经收录在set中时,便找到了该节点

// 算法写在一个类里
class Solution {
public:
    ListNode* detectCycle(ListNode* head) {
        set<ListNode*> node_set;
        while (head)
        {
            if (node_set.find(head) != node_set.end())
                return head;
            node_set.insert(head);
            head = head->next;
        }
        return NULL;
    }
    
};


// 以下为测试
int main() {
    // c1结点为两链表相交的结点
    ListNode a(1);
    ListNode b(2);
    ListNode c(3);
    ListNode d(4);
    ListNode e(5);
    ListNode f(6);
    ListNode g(7);
    a.next = &b;
    b.next = &c;
    c.next = &d;
    d.next = &e;
    e.next = &f;
    f.next = &g;
    g.next = &c;
    Solution solve;
    ListNode* p = solve.detectCycle(&a);
    if (p)
        cout << "链表有环,环的第一个结点为:" << p->val << endl;
    else
        cout << "链表无环" << endl;
    return 0;
}

结果:

链表有环,环的第一个结点为:3

方法二:快慢指针

初始化两个指针指向头结点,第一个指针速度是1,第二个指针速度是2,即第一个指针每次遍历一个结点,第二个指针每次遍历两个结点,当他们相遇时,便说明了该链表存在环(女少口阿)
而这种办法初步看只能求出是否有环,但求不出具体环的初始位置结点,故需要进一步分析:
求环初始结点

————图片来自小象学院教程课件
重点是这句话:从head和meet(即相遇的点)出发,相遇即为环的起点(女少口阿*2)
代码:

// 算法写在一个类里
class Solution {
public:
    ListNode* detectCycle(ListNode* head) {
        ListNode* fast = head; // 快指针
        ListNode* slow = head; // 慢指针
        ListNode* meet = NULL; // 相遇结点
        while (fast)
        {
            slow = slow->next;
            fast = fast->next;
            if (!fast)
                return NULL;
            fast = fast->next;
            if (fast == slow) {
                meet = fast;
                break;
            }
        }
        if (meet == NULL)
            return NULL;
        while (head&&meet)
        {
            if (head == meet)
                return head;
            head = head->next;
            meet = meet->next;
        }
        return NULL;
    }
    
};

就执行用时和内存消耗来看,用set都是比较不友好的,用普通算法就贼省时省内存 |* ̄ー ̄|

ps: 小象学院教程 https://www.bilibili.com/video/BV1GW411Q77S?t=7029&p=2 的笔记
LeetCode题号: 142

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值