【数据结构】链表OJ特别篇 —— 面试情景带你深度剖析 环形链表系列问题 复制带随机指针的链表

news2024/11/26 0:38:24

文章目录

  • 0. 前言
  • 1. 环形链表
  • 2. 环形链表延伸问题
  • 3. 环形链表 II
  • 4. 复制带随机指针的链表
  • 5. 结语

0. 前言

Hello,大家好,我是anduin。这期的内容依然是链表OJ。但与前两期不同的是,这次我会模拟面试的情景,由浅入深,以生动形象的方式,带你一步步吃透这些OJ题。内容为 经典的环形链表系列问题、复制带随机指针的链表这一十分考验链表功底的题目 。总体来说,题目还是有一定难度的,所以,接下来打起精神,认真看完,相信你会收获很多!话不多说,我们这就开始!

注:本故事纯属虚构,仅为配合题目的讲解,如有雷同实属巧合

1. 环形链表

众所周知,单链表是面试的常考点,假设你明天准备二面。由于时间不够了,你的链表基础也还行,所以你打算背两道题目,万一就考到了呢?于是你在链表题集中翻到了这道题。

链接:141. 环形链表

描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。**注意:pos 不作为参数进行传递 。仅仅 是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false

示例1

img

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例2:

img

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例3

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示

  • 链表中节点的数目范围是 [0, 10^4]
  • -10^5 <= Node.val <= 105
  • pos-1 或者链表中的一个 有效索引

你一看题目,懵逼了。这带环链表可咋做啊!于是你翻开了力扣的答案册,看到了某个帅哥(假设是我)的题解。于是你打算看看。

思路(精讲)

做这道题目之前我们需要明确一点 不能遍历链表 ,因为链表带环。

链表带环就是链表的某个节点中存储的地址为这个节点前的某个节点的地址。而导致闭环 ,使遍历链表时无法停止,走不到空,无法停止。

所以我们这道题目采用的方法是 快慢指针

总体思路是这样的,快指针走两步,慢指针走一步。给定快指针 fast ,慢指针 slow ,初始值为链表的头。

设入环前的距离为 x 。当 slow 走了 x/2 时,fast 入环。fast 走了一段路程后,slow 入环,fast 开始追击 slow,最后 fastslow 相遇。

而这里面的走法,就和我们上篇博客中,求链表的中间节点的方法一样。奇数走到最后一个节点,偶数走到空。

如果走到这两个条件了,说明链表一定不带环。否则不会走到空,它们一定会相遇,为环形链表。

image-20221020215309760

image-20221020211918235

你一看思路,我去这么多!我就背个代码吧,反正到时候应该也就只考代码,我只要记住这个方法叫 快慢指针 就好了呗!
然后你背了两道题目后,准备睡觉。

2. 环形链表延伸问题

第二天,你进入了面试的房间。

你坐到面试官的对面。面试官笑嘻嘻地问你:“小伙子,环形链表 会吗”?然后笑眯眯地拿了一张纸给你,这张纸上恰好就是这道题。

你看到题目,心里十分兴奋,那不是我昨天背的题目吗!笑哈哈地说:“那可是我的拿手好戏!” 然后提笔唰唰唰地就把题目写完了。

面试官看了一眼,眉头一皱,嘴角一抿,然后恢复笑容,说:“那我考考你,你是怎么想到的呀?”

你一听,以为面试官不知道你的方法,然后自信地说:“ 快慢指针 !”但是说完你后悔了,面试官问的是怎么想到的,这我咋会,我只会写,我说不出来呀…

面试官听到这里,好像察觉到了你内心的慌张,微微一笑,说:“那么你这么懂这个方法,那我问你几个问题吧!”

好了注意了,大家!接下来,请听题:

问题1:“为什么 slowfast 指针一定会在环中相遇?会不会错过,永远追不上?请证明一下?”

听到这个问题,你内心一紧,表情略微苦涩。面试官观察到了你的表情,笑容越发嚣张,继续问:

问题2:“为什么 slow 走一步,fast 走两步?能不能 fast 一次走 n 步 (n > 2) ?请证明一下?”

你懵了,说:“我不会…。”

面试官笑着对你说:“小伙子,你还是太嫩了呀!想知道这是为啥吗?”

你十分憋屈地说:“不知道。您能讲讲吗?”

面试官歪嘴一笑:“说,想学啊?我教你啊!”

于是面试官就开始了他的表演,期间举止十分嚣张,一言一语透露着自信。

接下来不会的小伙伴听好了,面试官(也就是我,哎嘿)来为大家讲问题!


问题1:“为什么 slowfast 指针一定会在环中相遇?会不会错过,永远追不上?请证明一下?”

第一步:slowfastfast 一定是先进环。这时 slow 走了入环前距离的一半。

第二步:随着 slow 进环,fast 已经在环里走了一段了。走了多少跟环的大小有关。

假设 slow 进环时,slowfast 的距离是 NN 的长度一定小于环。

image-20221020213756047

fast 开始追 slowslow 每次往前走 1 步,fast 往前走 2 步。每追一次,判断一下是否相遇。

每追 1 次,fastslow 的距离变化:N -> N - 1 -> N - 2 … 1 -> 0.

每追 1 次,距离减少 1 。它们最后的距离减到 0 时,就是相遇点。

image-20221020214504867

所以说,她逃他追,她插翅难飞。
额,不对,是快指针走两步一定会追到慢指针。
嗯对,接下来看下一个问题。


问题2:“为什么 slow 走一步,fast 走两步?能不能 fast 一次走 n 步 (n > 2) ?请证明一下?”

既然面试官这么问了,那么我们不妨走 n(n > 2) 步试一下。假设我们 slow 走一步,fast 走三步。

image-20221109172301272

它们之间的 距离变化 如下:

N 是偶数N 是奇数
NN
N - 2N - 2
N - 4N - 4
N - 6N - 6
21
0-1
可以追上这一次追不上

注: N 是 fastslow 之间的距离。

N奇数 时,如果 fast 走 3 步, slow 走 1 步,一个周期是肯定追不上的。走到最后它们之间的距离变为 -1 ,意味着现在 fastslow 前面一步,它们之间的距离变为 c - 1 。(c 是环的长度)

而长度一旦为 c-1 就有会引申出两种情况,看下图:

image-20221020223433145
我们这里已经 初步证明 了当 fast 一次走 n(n > 2) 步时,fast 是不一定可以追上 slow 的。

举了一个 fast奇数步 的例子,我们再举一个 fast 一次走 偶数步 的例子。

假设 fast 一次走 4 步,slow 一次走 1 步。

N 是 3 的倍数N 不是 3 的倍数(N是 1 的倍数)N 不是 3 的倍数(N 是 2 的倍数)
NNN
N - 3N - 3N - 3
N - 6N - 6N - 6
N - 9N - 9N - 9
321
0-1-2
可以追上这一次追不上这一次追不上

假设 c 是环的长度。

-1 意味着距离是 c - 1,-2 意味着距离是 c - 2。

如果 c - 1 和 c - 2 是 3 的倍数就可以追上,否则就追不上。

然后就可以以此类推,我就不多赘述了~

结论fast 走 2 步,slow 一定可以追上,因为它们的距离逐次减 1 。但是当 n > 2 时,不一定会相遇。


随后面试官再次笑眯眯地问:“同学,你懂了吗?”

你说:“我懂了,请问帅气的面试官,可以再给我一次机会吗?”

面试官本来戏谑的笑容瞬间灿烂了起来,说:“其实我一眼看你就不简单啊哈哈!孺子可教也,那么我就再给你一次机会,这次你可要接好了!本道题目叫做:环形链表 II !

于是面试官带着笑容开始介绍起了题目~

3. 环形链表 II

链接:142. 环形链表 II

描述

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例1:

img

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例2

img

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例3

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

提示

  • 链表中节点的数目范围在范围 [0, 10^4]
  • -10^5 <= Node.val <= 10^5
  • pos 的值为 -1 或者链表中的一个有效索引

一见到这个题目,你心里一慌,但是你知道这是你最后的机会。所以你疯狂地思考。

你脑子中一时闪过了整个宇宙,又想到了 快慢指针

你想着:“既然是要求 链表的入环点,那么我用 环形链表 的方法找到 交点 ,我又双叒叕看过某位帅气的博主(还是我)的上一篇博客,里面有个叫做 相交链表 的问题,那么我把这个 入环的第一个节点 看作是 两个相交链表的尾结点 不就可以了,这就转换成了链表相交的问题了!我真是个天才!”

于是你自信的写下了你的思路。

思路1

先利用 快慢指针 ,以 环形链表 的解法,找到 fastslow 相交的点。然后将这个 交点 给为 meetnode 。作为两条新链表的尾。那么 meetnode->next 为某条新链表的头。然后 入环点 ,就可以看做是两条链表的交点。

然后就是 相交链表 的做法,我就不多赘述了~

image-20221020234444674

代码:

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode* fast, *slow;
    fast = slow = head;
    struct ListNode* tail = NULL;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        // 相遇
        if (fast == slow)
        {
            tail = slow;
            break;
        }
    }
    // 没有相遇
    if (tail == NULL)
    {
        return NULL;
    }
    struct ListNode* newHead = tail->next;
    int lenH = 1, lenN = 1;
    struct ListNode* curH = head, *curN = newHead;
    while (curH != tail)
    {
        lenH++;
        curH = curH->next;
    }
    while (curN != tail)
    {
        lenN++;
        curN = curN->next;
    }
    struct ListNode* longList = lenH > lenN ? head : newHead;
    struct ListNode* shortList = lenH > lenN ? newHead : head;
    int gap = abs(lenH - lenN);
    while (gap--)
    {
        longList = longList->next;
    }
    while (longList != shortList)
    {
        longList = longList->next;
        shortList = shortList->next;
    }    
    return longList;
}

面试官看了你的做法,点点头,说:“小伙子很不错嘛!知道举一反三!看在你这么聪明的份上,我再教你个厉害的!怎么样?”

你点点头,于是面试官开始了他的讲解。看思路2↓


思路2(精讲)

面试官拿着笔,在纸上写下了三个大字:“公式法。”

面试官举着笔,不可一世地说:“这个方法的难点在于公式推导的过程,只要推导出了公式,解题就变得十分简单。”

然后眉飞色舞地继续说:“先把结论告诉你吧:一个指针从 相遇点 开始走,一个指针从 链表头 开始走,它们会在 环的入口点 相遇。

接下来,就让我来为你推导公式:

image-20221021131418644

由于 fast 的速度是 slow 的 2 倍。

所以便可以得出这个式子:2 ( L + x ) = L + N * c + x,而这个式子又可以进行推导:

2 ( L + x ) = L + N * c + x
            ↓
      L + x = N * c
            ↓
      L = N * c - x
            ↓
      L = ( N - 1 ) * c +  c - x 

其实这里 公式已经推导 完成:L = ( N - 1 ) * c + c - x 。但是这个公式到底是什么意思?

image-20221021134653612

根据这个我们也就可以做出这道题目了。

image-20221021134903936

讲完,面试官得意地笑着说:“怎么样,同学?你学会了吗?”

你说:“学废了学废了,我感觉我的链表水平更上一层楼~” 但是说完你又感觉到了不对劲,面试官又展现出他邪魅的笑容。

面试官说:“那么你很懂咯,你只要再把这道题目写出来,你就通过本次面试!怎么样,你有信心吗?”

你内心略微慌张,但是表面稳如老狗,说到:“来吧!”

“好的,接下来,这道题目叫做:复制带随机指针的链表!

4. 复制带随机指针的链表

链接:138. 复制带随机指针的链表

描述

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

例如,如果原链表中有 XY 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 xy ,同样有 x.random --> y

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0n-1);如果不指向任何节点,则为 null
你的代码 接受原链表的头节点 head 作为传入参数。

示例1

img

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例2

img

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例3

img

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

提示

  • 0 <= n <= 1000
  • -10^4 <= Node.val <= 10^4
  • Node.randomnull 或指向链表中的节点。

看到这道题目后,你的第一感觉是,这个链表结构含有 三个成员

struct Node
{
  	int val;
    struct Node* next; // 下一个节点的地址
    struct Node* random; // 指向随机节点的指针
};

然后你看到 复制 两字,你和面试官说:“这不是只要复制原链表的每个节点,将其链接起来不就行了?”

面试官听到这句话,优哉游哉地问:“那你的 random 呢?这个你怎么复制?”

你一听,顿时感觉有点心慌。心里想:“对啊,这道题目哪有这么简单。题目里说了它是 深拷贝 ,那么就应该完全复刻啊!并且我即使知道了原链表中和 random 链接的节点,我也不知道 random 和它的相对位置啊!这到底该咋办?”

面试官试着引导你的思路:“不知道你有没有这样的经历,我之前高中上英语课老师要求我们当场写阅读理解时,我虽然有答案。可这答案可不是那么好 copy 的。“

面试官拿起水杯,喝了口水,继续说:“为了不让老师发现,你得在原题目后 偷偷 写上答案。虽然你知道答案,但是你 找不到答案的位置 啊,所以你还得 通过 这份答案,画出答案所在的位置。然后为了防止老师发现你 copy 的痕迹,你得将你 copy 的答案和你划出的答案位置 串联 起来,并且抹除 掉之前的痕迹。你之前有过这样吗?”

你一听,恍然大悟,说到:“哦!我明白了!偷偷写上答案 是我可以在原链表中每个节点的后面,复制这个节点,插入到原节点和下一个节点之间;通过答案画出答案所在的位置 就相当于我知道 复制的节点是在原节点的后面 ,那么如果我已经知道原节点的 random 那么我 复制节点的 random 不就是 原节点的randomnext节点串联答案,抹除痕迹 就是将 复制节点 链接为新链表,和原链表断开链接,恢复原链表!我悟了!”

面试官听了点了点头,说道:“请开始你的表演!友情提示,虽然你的思路差不多对了,但是注意把控细节哦~”

思路(精讲)

思路其实在上面已经描述的差不多了,所以这里说一下细节。

首先,我们给定一个 copy 节点。在原链表每个节点的后面和这个节点的下一个节点之间插入 copy 节点。

这里就对细节有一定的要求。我们就把遍历原链表的节点叫做 cur 吧。

如果 cur 为空,则不进行拷贝。我们插入的 copy 节点是 动态开辟 的。我们需要将 copy 链接到 cur->next ,然后在让 cur->next 给定为 copy 。随后 cur 就需要原节点的后方,也就是当前 copy 节点的 next 。这就考察了 任意插入元素

其次,根据原节点 random ,处理 copy 节点的 random 。

其实我们现在已经将 copy 节点和 原链表建立了联系。

原链表的 random 为 cur->random 、而我们插入的 copy 节点也需要链接。如果我们原链表的当前节点的 random 为 cur->random ,那么我的 copy 节点的 random 节点的相对位置应该和当前节点相同。而我们的当前节点的 random 的后方的 拷贝节点 就是这个 copy 节点的 random 。那么我 copy->random 就等于 cur->random->next 。这样不就链接起来了?

这过程中只要处理好迭代关系就可以了,但是需要注意,当 random 指向为 NULL 时,拷贝处也为 NULL

最后,复制节点链接为新链表,原链表恢复。

完成这一步,我们需要 copyheadcopytail 作为复制链表的头和尾。

而复制节点链接为新链表的过程实际上就是 尾插 。所以要注意一下 空链表尾插正常尾插 的情况。

并且在这过程中,将原链表的链接逐渐恢复,这些就需要自己把控了~

image-20221021215156043

image-20221021215127513

image-20221021222203576

image-20221021180040573

代码

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) 
{
	struct Node* cur = head;

    // 1. 在原节点后插入复制节点
    while (cur)
    {
        // 插入复制节点
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
       
        copy->next = cur->next;
        cur->next = copy;

        // cur往后迭代
        cur = copy->next;
    }

    // 2. 根据原节点的random,处理复制节点的random
    cur = head;

    while (cur)
    {
        // copy节点在cur的后面
        struct Node* copy = cur->next;

        if (cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }

        cur = copy->next;
    }

    // 3. 复制节点链接为新链表,原节点恢复

    struct Node* copyHead = NULL, *copyTail = NULL;
    cur = head;

    while (cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;// 记录原链表的下一个节点

        // 复制节点链接为新链表(本质为尾插)
        if (copyTail == NULL)
        {
            copyHead = copyTail = copy;
        }
        else
        {
            copyTail->next = copy;
            copyTail = copy;
        }

        cur->next = next;// 恢复链接
        cur = next;
    }
    return copyHead;
}

解完这道题目后,你自信地说:“面试官,你看我行吗?”

面试官笑着说:“哈哈哈,小伙子厉害呀!我为你点赞!本次面试你通过了,回去等通知吧!💇‍♂”

5. 结语

到这里本篇博客就到此结束了。

说真的,博主还是第一次以这种形式写博客,不知道大家的观感如何。希望这篇博客能帮助大家理解这些OJ题,因为 环形链表系列问题 是十分经典的面试题,而普通的讲解我感觉过于生涩,这样可能更容易理解一些,而且偶尔皮一下还是很不错的(doge)。

还是老规矩,大家在看完这些题目后还是亲自去画画图,实践一下。多写多练才能学好数据结构。

这期结束,链表OJ也就到此收官了。之后我会陆续为大家带来博主在学习数据结构时总结的知识点,更多精彩内容,敬请期待~

如果觉得anduin写的还不错的话,还请一键三连!如有错误,还请指正!

我是anduin,一名C语言初学者,我们下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

冶金行业数字化供应链管理系统:赋能企业端到端供应链优化,推动行业数字化变革

作为国之重器&#xff0c;冶金行业在国家大基建战略的支持下&#xff0c;迎来了新一轮的发展良机&#xff0c;然而冶金行业整体产能过剩、对于产业链下游依赖严重等情况依然突出&#xff0c;机遇与挑战并存&#xff0c;在此环境下&#xff0c;如何在激烈的竞争中提升企业自身竞…

多对一和一对多的处理P21,P22

多对一&#xff1a; 按照查询嵌套处理&#xff1a; StudentMapper&#xff1a;&#xff08;接口很简单需要返回一个List&#xff09; package com.Li.dao;import com.Li.pojo.Student; import org.apache.ibatis.annotations.Select;import java.util.List;public interface …

无人机和热成像

当它变得可见时&#xff0c;看不见的世界是一个令人惊叹的景象。 热成像就是这样&#xff0c;透过使用专门的摄影机和技术&#xff0c;使看不见的红外光谱可见。 我们周围那个无形的世界隐藏着什么&#xff0c;这是一个完整的隐藏世界。 图片来源&#xff1a;Keith Davis/热成像…

腾讯面试真题 | 没在我八股文列表里。。。

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

零基础自学javase黑马课程第十天

零基础自学javase黑马课程第十天 ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f52e;本文由京与旧铺原创&#xff0c;csdn首发&#xff01; &#x1f618;系列专栏&#xff1a;java学习 &#x1f4bb;首发时间&#xff1a;&#x1f39e;2022年11月1日&#x…

【MySQL】深入理解MySQL索引优化器工作原理

本文导读 本文将解读MySQL数据库查询优化器&#xff08;CBO&#xff09;的工作原理。简单介绍了MySQL Server的组成&#xff0c;MySQL优化器选择索引额原理以及SQL成本分析&#xff0c;最后通过 select 查询总结整个查询过程。 一、MySQL 优化器是如何选择索引的 下面我们来…

2022年最新浙江建筑特种工(施工升降机)真题题库及答案

百分百题库提供特种工&#xff08;施工升降机&#xff09;考试试题、特种工&#xff08;施工升降机&#xff09;考试预测题、特种工&#xff08;施工升降机&#xff09;考试真题、特种工&#xff08;施工升降机&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考…

web前端期末大作业——基于html+css+javascript学生宿舍管理系统网站

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

双十一到了,当我用Python采集了电商平台所有商品后发现....

Python采集电商平台写在前面环境及模块案例实现思路代码展示效果展示最后写在前面 这不是双十一快到了&#xff0c;为了以最优惠的价格买到自己想买的商品&#xff0c;我不惜用Python把ya ma xun 所有商品撸了一遍。 环境及模块 使用环境 python 3.8 pycharm 2021 模块及安…

重磅发布 | 更快、更强的 .NET 7

.NET Conf 2022在11⽉8⽇11点正式开始了&#xff0c;为期三天的会议&#xff08;11⽉8-10⽇&#xff09;&#xff0c;围绕 .NET 7 展开。相信各位⼩伙伴都已经开始安装 .NET 7 正式版本以及相关的开发⼯具。这次 .NET 7 围绕传统的 C#&#xff0c;ASP.NET Core, Blazor, .NET M…

如何用python给女神写一封照片情书?亲测表白率100%~

嗨害大家好鸭&#xff01;我是小熊猫❤ 咳咳…大家都问我 是怎么追到我女神的&#xff0c; 斗胆来分享一下俺的小教程&#x1f4a8; 实现步骤 想要实现把情书写在像素中&#xff0c; 那么我们就需要用到pillow这个神器。 众所周知&#xff0c;图片是由无数个像素所组成的&…

【Spring Boot项目】个人在线音乐播放器

文章目录项目简介数据库表的设计拦截器及返回数据格式注册功能登陆功能音乐列表相关业务查询功能上传音乐播放音乐收藏音乐删除功能删除单个音乐批量删除音乐收藏列表查询收藏的音乐取消收藏注销功能项目简介 本项目主要是实现了在线播放音乐的功能&#xff0c;用户可以随时登…

[RCTF 2019]Nextphp

知识点&#xff1b;利用 FFI 绕过 disable_functionFFI 介绍与利用 首先 FFI 肯定要开&#xff0c;且 PHP 版本肯定要早 7.4 以上 简介&#xff1a; FFI &#xff0c;可以让我们直接在PHP脚本中调用C语言写的库中的函数。 FFI 的安全性问题 FFI虽然给了我们很大的灵活性&am…

人脸视频检索系统设计(C++)

目录 人脸检索系统框架的构建 1 一.软件实现的主要界面 1 二.软件的需求概括 1 三.软件代码设计过程中需要注意的问题 2 四.程序到目前为止产生的诸多缺陷 4 五.程序的详细设计过程 4 1.输入部分的设计 4 2.检测结果部分的设计过程 10 人脸检索系统框架的构建 ------FaceMFC_v…

腾讯148道面试题,(程序员必备学习方向)全会拿45Koffer没问题

相信你可能经历过这些&#xff1a; 已经工作两三年了&#xff0c;每个项目都会加班加点全力以赴去完成&#xff0c;薪资增长幅度却不如人意。听说年后离职的老同事&#xff0c;金三刚拿下高薪offer&#xff0c;年薪直奔50万了。由于现在的公司接触不到新技术&#xff0c;对自己…

思科网络部署实验

作者介绍&#xff1a; 作者&#xff1a;小刘在C站 每天分享课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; 夕阳下&#xff0c;是最美的绽放。 今天带个大家一个实验&#xff0c;为网络篇的综合实验&#xff0c;有能力的可以试一试不会的可以私信小刘。 配…

排序算法:插入排序、冒泡排序、选择排序、希尔排序、堆排序、快速排序、归并排序

排序算法相关总结&#xff0c;涉及的排序算法有&#xff1a;插入排序、冒泡排序、选择排序、希尔排序、堆排序、快速排序、归并排序&#xff08;动图不是自己画的&#x1f31e;&#xff09;。 目录1.插入排序2.冒泡排序3.选择排序4.希尔排序5.堆排序6.快速排序7.归并排序总结稳…

【Revit二次开发】模型中存储数据——参数和外部存储(Parameter, Schema and Entity)

模型中存储数据参数读取写入外部存储SchemaEntity快速获取外部存储参数参数 在Revit平台API中&#xff0c;每个图元对象都有参数属性&#xff0c;它是隶属于图元所有属性的集合&#xff0c;在此集合中更改属性值。 每个图元的参数都有一个与之关联的ElementId类型的ID大多数参…

KMP算法

文章目录KMP算法KMP算法 KMP算法要解决的问题就是在字符串&#xff08;也叫主串&#xff09;中的模式&#xff08;pattern&#xff09;定位问题。说简单点就是我们平时常说的关键字搜索。模式串就是关键字&#xff08;接下来称它为P&#xff09;&#xff0c;如果它在一个主串&…

C++图的建立---邻接矩阵-----邻接表

目录 图的表示方式 邻接矩阵 邻接表 图的遍历 深度优先遍历 深度优先遍历算法步骤&#xff1a; 图的广度优先遍历 广度优先遍历算法步骤: 图的邻接矩阵存储来创建图 代码 运行结果&#xff1a; 图的邻接表存储来创建图 如下图&#xff1a; 运行结果&#xff1…