力扣刷题:单链表OJ篇(下)

大家好,这里是小编的博客频道

小编的博客:就爱学编程
很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

目录


废话不多说,我们直接看题。

1.环形链表

(1)题目描述



(2)解题思路

快慢指针
但要注意:最好使得快指针fast 一次走两步,慢指针slow 一次走一步使得两指针的速度之差为1 。这样就不可能会出现有环不相交的问题。

代码实现:

c 复制代码
bool hasCycle(struct ListNode *head) {
    //快慢指针看是否会相遇,但最好快指针一次走两步,慢指针一次走一步,就不会出现有环却不相遇的情况
    struct ListNode* fast = head, * slow = head;
    if(head == NULL) return false;
    while(fast && fast->next){
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow){
            return true;
        }
    }
    return false;
}

(3)复杂度分析

  • 时间复杂度:O(N),其中 N 是链表中的节点数。
  • 空间复杂度:O(1)。我们只使用了两个指针的额外空间。

2.环形链表2

(1)题目描述



(2)解题思路

思路一:先找到相交点再把相交的点next指针指向空,这样就转变成了头指针head 和·相遇点的next 指针找交点问题。

代码实现:

c 复制代码
 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if (headA == NULL || headB == NULL) {
        return NULL;
    }
    struct ListNode *p1 = headA, *p2 = headB;
    while (p1 != p2) {
        p1 = p1 == NULL ? headB : p1->next;
        p2 = p2 == NULL ? headA : p2->next;
    }
    return p1;
}

struct ListNode *detectCycle(struct ListNode *head) {
    if (head == NULL) return NULL;
    struct ListNode* fast = head, * slow = head;
    while (fast && fast->next) {
        //先走,防止因为头指针相等
        fast = fast->next->next;
        slow = slow->next;
       if (fast == slow) {
            struct ListNode* ptr = fast->next;
            fast->next = NULL;
            return getIntersectionNode(ptr, head);
        }
    }
     return NULL;
}

思路二:借助定理------两个快慢指针他们相交于环内一位置,而一指针从该位置开始走,同时另一从链表的头结点开始走,它们最终会第一次相交于环开始的那个节点。(怎么得到这个定理的一定要掌握,因为HR问到会问这个)
定理推导:

  • 我们使用两个指针,fast与 slow。它们起始都位于链表的头部。随后,slow 指针每次向后移动一个位置,而 fast 指针向后移动两个位置。如果链表中存在环,则 fast 指针最终将再次与 slow 指针在环中相遇。
  • 设链表中环外部分的长度为 a。slow 指针进入环后,又走了 b 的距离与 fast 相遇。此时,fast 指针已经走完了环的 n 圈,因此它走过的总距离为 a + n(b + c) + b = a + (n + 1)b + nc。
  • 根据题意,任意时刻,fast 指针走过的距离都为 slow 指针的 2 倍。因此,我们有a + (n + 1)b + nc = 2(a + b)⟹a = c + (n−1)(b + c)
  • 有了a = c + (n−1)(b + c)的等量关系,我们会发现:从相遇点到入环点的距离加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离。
  • 因此,当发现 slow 与fast相遇时,我们再额外使用一个指针 ptr。起始,它指向链表头部;随后,它和 slow 每次向后移动一个位置。最终,它们会在入环点相遇。

代码实现:

c 复制代码
struct ListNode *detectCycle(struct ListNode *head) {
    //这题要做出就一定要推出一个定理:两个快慢指针他们相交于环内一位置,而一指针从该位置开始走,同时另一从链表的头结点开始走,它们最终会第一次相交于环开始的那个节点。(怎么得到这个定理的一定要掌握,因为HR问到会问这个)
    struct ListNode* fast = head, * slow = head;
    if (head == NULL) return NULL;
    while (fast && fast->next) {
        //先走,防止因为头指针相等
        fast = fast->next->next;
        slow = slow->next;
       if (fast == slow) {
        struct ListNode* ptr = head;
            while(ptr != slow){
                ptr = ptr->next;
                slow = slow->next;
            }
            return ptr;
        }
    }
     return NULL;
}

(3)复杂度分析


快乐的时光总是短暂,咱们下篇博文再见啦!!!如果小编的文章会对你有帮助的话不要忘了,记得给小编点赞、收藏支持一下,在此非常感谢!!!

相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark4 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218614 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法