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

每日精讲:环形链表、两个数组中的交集、随机链表的复制
 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

使用LLaMA-Factory对GLM-4-9B-Chat进行LoRA微调

使用LLaMA-Factory对GLM-4-9B-Chat进行LoRA微调 在大模型应用日益普及的今天,如何快速、低成本地定制一个符合特定场景需求的语言模型,已经成为开发者和企业关注的核心问题。直接全参数微调动辄数十GB显存消耗,对大多数团队而言并不现实。而像 LoRA(Low-Rank Adaptation) 这样的高效微调技术,配合如 LLaMA-Factory 这类开箱即用的框架,正让“平民化”大模型定制成为可能。 本文将以 GLM-4-9B-Chat 为例,带你从零开始完成一次完整的 LoRA 微调流程——从环境配置、数据清洗到训练部署,最终得到一个可独立运行的专属模型。整个过程无需深入理解底层原理,也能在单卡 A10/A100 上顺利完成。 环境准备:搭建可编辑的开发环境 首先确保你的系统已安装 Python ≥ 3.10 和支持 CUDA 的 PyTorch 版本(推荐 torch==2.1.0+cu118 或更高)

By Ne0inhk
开源强化学习框架RLinf:面向具身和智能体的强化学习基础设施

开源强化学习框架RLinf:面向具身和智能体的强化学习基础设施

清华大学等发布RLinf:面向具身和智能体的强化学习基础设施 RLinf 是一个灵活且可扩展的开源强化学习基础设施,是以清华大学、北京中关村学院、无问芯穹为核心,还联合了北京大学、加州大学伯克利分校等机构共同参与设计并开源。这是一个面向具身智能的“渲训推一体化”大规模强化学习框架,专门为具身人工智能和智能体人工智能而设计。RLinf 中的“inf”代表“基础设施” Infrastructure,突显了它作为下一代训练强大骨干的作用。它也代表“无限” Infinite,象征着该系统支持开放式学习、持续泛化以及智能发展中的无限可能。 RLinf具身智能AI强化学习训练平台框架 参考链接: https://github.com/RLinf/RLinf Franka真机强化学习 本文档给出在 RLinf 框架内启动在 Franka 机械臂真机环境中训练任务的完整指南, 重点介绍如何从零开始训练基于 ResNet 的 CNN 策略以完成机器人操作任务。 主要目标是让模型具备以下能力: 1. 视觉理解:处理来自机器人相机的 RGB 图像。 2.

By Ne0inhk

腾讯Hunyuan-MT-7B翻译模型完全指南:2025年开源AI翻译的新标杆

🎯 核心要点 (TL;DR) * 突破性成就:腾讯混元MT-7B在WMT25全球翻译竞赛中获得30/31项第一名 * 双模型架构:Hunyuan-MT-7B基础翻译模型 + Hunyuan-MT-Chimera-7B集成优化模型 * 广泛语言支持:支持33种语言互译,包括5种中国少数民族语言 * 完全开源:2025年9月1日正式开源,提供多种量化版本 * 实用部署:支持多种推理框架,提供详细的部署和使用指南 目录 1. 什么是腾讯混元翻译模型 2. 核心技术特点与优势 3. 双模型架构详解 4. 支持语言与使用方法 5. 性能表现与竞赛成绩 6. 部署与集成指南 7. 实际应用场景 8. 常见问题解答 什么是腾讯混元翻译模型 {#what-is-hunyuan-mt} 腾讯混元翻译模型(Hunyuan-MT)是腾讯在2025年9月1日开源的专业翻译AI模型,由两个核心组件构成: * Hunyuan-MT-7B:7B参数的基础翻译模型,专注于将源语言文本准确翻译为目标语言 * Hunyuan-MT-Chimera-7B:业界首个开源翻译集成

By Ne0inhk

coze-loop开源可部署:MIT协议,支持二次开发与私有化定制

coze-loop开源可部署:MIT协议,支持二次开发与私有化定制 1. 项目简介 coze-loop 是一个基于 Ollama 本地大模型框架的 AI 代码优化工具,采用 MIT 开源协议,支持完全私有化部署和二次开发。这个工具的核心价值在于:让开发者能够像请了一位世界级软件工程师一样,随时对代码进行专业级优化。 想象一下这样的场景:你写了一段能运行的代码,但总觉得不够优雅、效率不高,或者可读性差。传统做法是去论坛提问、查阅文档,或者请同事帮忙review。现在,你只需要把代码粘贴进去,选择优化目标,几秒钟就能获得专业级的优化方案和详细解释。 核心能力包括: * 代码运行效率优化(减少执行时间,降低资源消耗) * 代码可读性提升(让代码更清晰易懂,便于团队协作) * 潜在Bug修复(发现并修复隐藏的问题) * 详细优化说明(不仅给结果,还解释为什么这样优化) 2. 快速安装与部署 2.1 环境要求 coze-loop 对运行环境要求相对宽松,适合大多数开发环境:

By Ne0inhk