力扣刷题:单链表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)复杂度分析


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

相关推荐
涛ing24 分钟前
32. C 语言 安全函数( _s 尾缀)
linux·c语言·c++·vscode·算法·安全·vim
独正己身1 小时前
代码随想录day4
数据结构·c++·算法
利刃大大4 小时前
【回溯+剪枝】找出所有子集的异或总和再求和 && 全排列Ⅱ
c++·算法·深度优先·剪枝
皮卡丘のcoding4 小时前
蓝桥杯备赛练习题01
职场和发展·蓝桥杯
Rachela_z5 小时前
代码随想录算法训练营第十四天| 二叉树2
数据结构·算法
细嗅蔷薇@5 小时前
迪杰斯特拉(Dijkstra)算法
数据结构·算法
追求源于热爱!5 小时前
记5(一元逻辑回归+线性分类器+多元逻辑回归
算法·机器学习·逻辑回归
不过四级不改名6775 小时前
蓝桥杯嵌入式uart,iic,adc_scan模版
职场和发展·蓝桥杯
ElseWhereR5 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
Smark.5 小时前
Gurobi基础语法之 addConstr, addConstrs, addQConstr, addMQConstr
算法