每日精讲:环形链表、两个数组中的交集、随机链表的复制

每日精讲:环形链表、两个数组中的交集、随机链表的复制
 Hello大家好! 很高兴与大家见面! 给生活添点快乐,开始今天的编程之路。



我的博客:<但愿.

我的专栏:C语言题目精讲算法与数据结构C++

欢迎点赞,关注

一 环形链表

1.1题目链接:环形链表II

1.2题目描述:

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

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

1.3题目示例:

1.4题目思路:

在我的主页的题目精讲中讲过C语言的方法(快慢指针)C语言相对复杂,这里我们使用C++STL实现。这里使用到STL的set遍历链表如果链表中的节点不在set中就插入(注意这里不是插入节点的值,而是节点的指针,因为节点的值可能有几个相等);如果在就带环,并且该节点就是环入口点。

1.5解决代码

//1cur不在set对象中,就插入到set对象中 //2cur在set对象中就带环,并且该节点就是环入口点 class Solution { public: ListNode *detectCycle(ListNode *head) { set<ListNode*> s; ListNode* cur = head; while(cur) { auto it = s.find(cur);//查找cur是否在set对象中 if(it == s.end())//cur不在set对象中,就插入到set对象中 { s.insert(cur); } else//cur在set对象中就带环,并且该节点就是环入口点 { return *it } cur = cur->next; } return nullptr; } };

二 两个数组中的交集

2.1题目链接:两个数组的交集

2.2题目描述:

给定两个数组 nums1 和 nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

2.3题目示例:

示例 1:输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2]

示例 2:输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[9,4] 解释:[4,9] 也是可通过的

2.4题目思路:

思路1:一个数组的每个值到另一个数组中遍历,这种虽然可行,但是和拿哪个数组中的值到哪个数组中遍历有关例如示例2如果拿nums1中的每个值到nums2中遍历可行,但是如果拿nums2中的每个值到nums1中就会得到结果[9,4,9,4]是不正确的,所以这种方法不行。

思路2(正确思路):先将两个数组去重(要先排序只有排序了才能真正的去重)【去重可用STL中是set;也可以用算法库中的去重算法std::unique】,在拿一个数组中的值分别到另一个数组中找(使用STL->set->count,最后将遍历找到的插入到一个容器中返回即可。

2.5解决代码:

class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { //去重 set<int> s1(nums1.begin(),nums1.end()); set<int> s2(nums2.begin(),nums2.end()); vector<int> v; //将一个数组中的值依次到另一个数组中查找 for(auto e : s1) { if(s2.count(e)) { v.push_back(e);//在另一个数组中插入到一个容器中 } } return v; } };

2.6作用:

从上面来看这个是没有什么作用的,但是现实生活中不只是用来查找交集的,一般是要找交/差/并集,这时候就有著名的对比算法。

两个数组中找交/差/并集的整体思路(对比算法):

【示例】使用对比算法找交集:

class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { set<int> s1(nums1.begin(), nums1.end()); set<int> s2(nums2.begin(), nums2.end()); // 因为set遍历是有序的,有序值,依次⽐较 // ⼩的++,相等的就是交集 vector<int> ret; auto it1 = s1.begin(); auto it2 = s2.begin(); while(it1 != s1.end() && it2 != s2.end()) { if(*it1 < *it2) { it1++; } else if(*it1 > *it2) { it2++; } else { ret.push_back(*it1); it1++; it2++; } } return ret; } };

【对比算法在生活中的应用】

例如我们要更换手机,而之前的手机中有许多的照片是要的,此时怎么办呢?这时候可以买个华为云,将华为云中的照片和之前手机中的照片进行对比,判断是否要导入到华为云中,而照片存在,但是照片可能存在更改,这时候可以比较照片最后的时间。所以这个对比算法在生活中还是有很多用处的。

三 随机链表的复制(两种解决办法C语言[了解思路]、C++)

3.1题目链接:随机链表的复制

3.2题目描述:

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

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

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

返回复制链表的头节点。

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

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。

你的代码接受原链表的头节点 head 作为传入参数。

3.3题目示例:


3.4题目思路:

3.5解决代码:

【c语言解决代码】注意利用这个了解思路

/**  * Definition for a Node.  * struct Node {  *     int val;  *     struct Node *next;  *     struct Node *random;  * };  */ typedef struct Node Node; //构造一个简单 Node* buyNode(int x) {     Node* newnode = (Node*)malloc(sizeof(Node));     newnode->val = x;     newnode->next=newnode->random = NULL;     return newnode; } //在原链表的基础上拷贝节点(即原链表的每个节点后面拷贝一个一样的节点) void AddNode(Node* head) {     Node* pcur = head;     while(pcur)     {         Node* newnode = buyNode(pcur->val);         Node* next = pcur->next;         newnode->next = next;         pcur->next = newnode;         pcur = next;     } } //设置新节点的random利用关系式 //copy(新节点)->random = pcur(原链表节点)->random->next; void setRandom(Node* head) {     Node* pcur = head;     while(pcur)     {         Node* copy = pcur->next;         if(pcur->random)         {             copy->random = pcur->random->next;         }         pcur = copy->next;     } } struct Node* copyRandomList(struct Node* head) {     if(head == NULL)//如果头节点为空要特殊处理     {         return head;     }     //1在原链表基础上拷贝节点并插入到原链表的每个节点之后     AddNode(head);     //2设置新节点的random     setRandom(head);     //断开新旧链表 //注意这里要返回新链表的根节点,所以这里要定义两个变量 //一个用于储存新链表的根节点位置,一个用于从新链表的根节点位置开始遍历。     Node* pcur = head;     Node* copyHead,*copyTail;     copyHead = copyTail = pcur->next;     while(copyTail->next)     {         pcur = copyTail->next;         copyTail->next = pcur->next;         copyTail = copyTail->next;     }     return copyHead; }

【c++使用STL解决代码】

上面讲了C语言的处理方法,由于出现一个很难处理的问题节点中的random(随机)节点怎么拷贝,如果通过节点中的值进行判断指向关系【如果一个节点的random指向的节点值是1,而节点值为1的节点不止一个有怎么解决呢?显然这种方法是不行的】,如果想走这种匹配关系,那只能暴力遍历,此时时间复杂度为O(N^2)不会,这是因为原链表和拷贝出的链表直接的节点没关系才导致的,C语言的处理方法是先拷贝在原链表中在就导致原链表和拷贝出的链表之间的节点有了关系。那C++怎么处理了,C++所以STL中的map由于储存map(原链表节点,拷贝链表的节点)这不就巧妙的将原链表和拷贝出的链表之间的节点联系起来了吗,可以通过原链表节点得到拷贝对应的节点。

【解决代码】

class Solution { public: Node* copyRandomList(Node* head) { map<Node*, Node*> nodeMap;//由于存在原链表节点和拷贝的节点,从而导致两者之间有关系 Node* copyhead = nullptr,*copytail = nullptr;//由于储存拷贝链表的根节点和遍历拷贝链表 Node* cur = head; while(cur) { if(copytail == nullptr)//如果为空特殊处理 { copyhead = copytail = new Node(cur->val); } else//如果不为空进行尾插 { copytail->next = new Node(cur->val); copytail = copytail->next; } // 原节点和拷⻉节点map kv存储 nodeMap[cur] = copytail; cur = cur->next; } // 处理random cur = head; Node* copy = copyhead; while(cur) { if(cur->random == nullptr)//如果原节点的random为空则拷贝节点的random也为空 { copy->random = nullptr; } else//如果原节点的random不为空则,则使用map[],传入参数原链表节点指针,得到拷贝出的对应节点 { copy->random = nodeMap[cur->random]; } cur = cur->next; copy = copy->next; } return copyhead; } };

本篇文章就到此结束,欢迎大家订阅我的专栏,欢迎大家指正,希望有所能帮到读者更好了算法与数据结构相关知识 ,觉得有帮助的还请三联支持一下~后续会不断更新算法与数据结构相关知识,我们下期再见。

Read more

用闲置Mac Mini部署OpenClaw(moltbot)实现你的专属金融AI分析师

用闲置Mac Mini部署OpenClaw(moltbot)实现你的专属金融AI分析师

在数字时代,每个人都需要一个24小时在线的智能工作伙伴。如果你恰好有一台闲置的Mac Mini,只需几个小时,就能将它变身为一个具备专业金融分析能力的AI助手。本文将手把手带你完成整个部署过程,让你拥有一个能对话、能分析、能监控的私人数字员工。 一、为什么选择Mac Mini+OpenClaw? 核心优势对比 传统方式Mac Mini+OpenClaw方案需要购买云服务器,持续付费利用闲置硬件,零额外硬件成本数据存储在第三方平台数据完全私有,存储在本地功能固定,难以定制可通过技能商店无限扩展功能需要专业技术维护一次性部署,长期稳定运行 特别是对于金融从业者、投资者以及对市场信息敏感的用户,这个方案能提供: * 7×24小时市场监控与预警 * 自然语言驱动的专业分析 * 完全私有的数据环境 * 可扩展的金融工具集成 二、完整部署流程图 graph A[开始部署] --> B{选择设备方案}; B --> C[闲置Mac Mini]; B --> D[

By Ne0inhk

开发者实操手册:Qwen3-Embedding-4B + llama.cpp部署教程

开发者实操手册:Qwen3-Embedding-4B + llama.cpp部署教程 1. 引言 随着大模型在语义理解、信息检索和知识管理等场景的广泛应用,高质量的文本向量化能力成为构建智能系统的核心基础。通义千问团队于2025年8月开源了 Qwen3-Embedding-4B ——一款专为高效文本嵌入设计的中等规模双塔模型。该模型以4B参数量实现了对32k长文本的支持,输出2560维高精度向量,并在MTEB多项基准测试中超越同尺寸模型。 本文将围绕 Qwen3-Embedding-4B 的本地化部署实践展开,重点介绍如何结合 llama.cpp 和 vLLM + Open WebUI 构建一个可交互、高性能的知识库服务系统。无论你是想在消费级显卡(如RTX 3060)上运行语义搜索,还是希望搭建支持多语言、长文档的企业级知识引擎,本教程都能提供完整可落地的技术路径。 2. Qwen3-Embedding-4B 模型特性解析 2.1 核心架构与技术亮点 Qwen3-Embedding-4B 是阿里云 Qwen3 系列中专注于「文本向量化」任务的专用模型,采用标准的 De

By Ne0inhk
LLaMA-Factory全流程训练模型

LLaMA-Factory全流程训练模型

🤗本文主要讲述在docker下使用LLaMA-Factory训练推理模型。 🫡拉取镜像 首先需要启动docker,然后在终端中输入: docker run -tid --gpus all -p 8000:8000 --name LLM -e NVIDIA_DRIVER_CAPABILITIES=compute,utility -e NVIDIA_VISIBLE_DEVICES=all --privileged=true ubuntu:20.04 * 这个命令启动了一个 Ubuntu 20.04 容器,使用所有可用的 GPU * 主机的 8000 端口映射到容器的 8000 端口 * 容器命名为 LLM,以特权模式运行容器 进入容器  docker exec -it LLM

By Ne0inhk

AI绘画终极指南:从零开始掌握智能创作技术 [特殊字符]

AI绘画终极指南:从零开始掌握智能创作技术 🎨 【免费下载链接】robo-diffusion 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/robo-diffusion 想要体验AI绘画的神奇魅力吗?Robo-Diffusion模型为您打开了通往智能艺术创作的大门!在这份完整的AI绘画技术解析中,我们将带您深入了解这项前沿技术,无需任何编程基础,轻松上手创作惊艳作品。 🚀 快速入门:五分钟开启AI绘画之旅 环境准备步骤: 1. 确保您的设备已安装Python 3.8或更高版本 2. 安装必要的依赖库:PyTorch、Transformers等 3. 下载模型文件到本地目录 模型下载命令: git clone https://gitcode.com/hf_mirrors/ai-gitcode/robo-diffusion 核心组件概览: * 文本理解模块:位于text_encoder/目录,负责解析您的文字描述 * 图像生成核心:在unet/

By Ne0inhk