力扣刷题:单链表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 指针在环中相遇。
  • 设链表中环外部分的长度为 aslow 指针进入环后,又走了 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)复杂度分析


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

相关推荐
原来是猿12 分钟前
蓝桥备赛(13)- 链表和 list(上)
开发语言·数据结构·c++·算法·链表·list
项目申报小狂人25 分钟前
高性能算法NGO!北方苍鹰优化算法(Northern Goshawk Optimization,NGO)
算法·数学建模
且听风吟ayan36 分钟前
leetcode day26 重复的子字符串
算法·leetcode·c#
仟濹1 小时前
【算法 C/C++】二维差分
c语言·c++·算法
*星星之火*1 小时前
【GPT入门】第9课 思维树概念与原理
gpt·算法·深度优先
海姐软件测试1 小时前
面试时,如何回答好“你是怎么测试接口的?”
测试工具·面试·职场和发展·postman
总斯霖1 小时前
题解:士兵排列
数据结构·c++·算法
稳兽龙2 小时前
P4268 [USACO18FEB] Directory Traversal G
c++·算法·换根dp
我是大咖3 小时前
c语言笔记 一维数组与二维数组
c语言·笔记·算法
誓约酱3 小时前
(每日一题) 力扣 283 移动零
linux·c语言·数据结构·c++·算法·leetcode