跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++算法

环形链表检测、数组交集计算与随机链表复制解析

针对环形链表环入口检测,利用哈希集合记录访问节点指针可快速定位;数组交集问题通过去重后遍历或双指针对比有序集合高效解决;随机链表深拷贝则提供 C 语言节点穿插法与 C++ 映射表法两种思路,前者节省空间后者逻辑更直观。

HadoopMan发布于 2026/3/23更新于 2026/5/34 浏览
环形链表检测、数组交集计算与随机链表复制解析

环形链表

题目描述

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

为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。注意不允许修改链表。

思路分析

在之前的讲解中我们讨论过 C 语言的快慢指针解法,虽然经典但实现稍显繁琐。这里我们直接使用 C++ STL 的 set 容器来简化逻辑。核心思想是遍历链表,将访问过的节点指针存入集合中。如果当前节点已经在集合里,说明遇到了环的入口;如果遍历结束都没发现重复,则无环。

关键点:插入的是节点的指针地址,而非节点的值。因为节点值可能重复,只有指针唯一性才能准确判断是否访问过该节点。

代码实现

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        std::set<ListNode*> s;
        ListNode* cur = head;
        while(cur) {
            auto it = s.find(cur);
            if(it == s.end()) {
                s.insert(cur);
            } else {
                return *it;
            }
            cur = cur->next;
        }
        return nullptr;
    }
};

两个数组中的交集

题目描述

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

思路分析

暴力遍历两个数组效率较低且容易出错。更优的方案是利用哈希集合去重。

  1. 去重:先将两个数组分别转换为 std::set,自动完成去重并排序。
  2. 查找:遍历其中一个集合,检查元素是否存在于另一个集合中。
  3. 对比算法优化:由于 set 遍历是有序的,也可以使用双指针法依次比较两个有序集合的元素,小的移动指针,相等则记录为交集。这种方法在处理大数据量时往往比嵌套查找更高效。

代码实现

class Solution {
public:
    vector<>  {
        
        ;
        ;
        vector<> v;
        
        
        ( e : s1) {
            (s(e)) {
                v.(e);
            }
        }
         v;
    }
};
int
intersection
(vector<int>& nums1, vector<int>& nums2)
// 利用 set 自动去重
std::set<int> s1(nums1.begin(), nums1.end())
std::set<int> s2(nums2.begin(), nums2.end())
int
// 遍历 s1,在 s2 中查找
for
auto
if
2.
count
push_back
return

对比算法实战示例:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        std::set<int> s1(nums1.begin(), nums1.end());
        std::set<int> s2(nums2.begin(), nums2.end());
        
        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;
    }
};

随机链表的复制

题目描述

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random,该指针可以指向链表中的任何节点或空节点。构造这个链表的深拷贝。深拷贝应该正好由 n 个全新节点组成,其中新节点的 next 指针和 random 指针也都应指向复制链表中的新节点。

思路分析

这道题的核心难点在于 random 指针的映射关系。原链表和拷贝链表之间没有天然联系,如何快速找到对应节点是关键。

方案一:C 语言节点穿插法(空间复杂度 O(1)) 不创建新链表结构,而是在原链表每个节点后插入一个拷贝节点。这样原节点 A 的拷贝就在 A->next。通过这种物理连接,A->random->next 就是 A->random 对应节点的拷贝。最后再断开链接恢复原状并提取新链表。

方案二:C++ 映射表法(空间复杂度 O(N)) 利用 std::map<Node*, Node*> 存储原节点到拷贝节点的映射。遍历时先建立所有节点的映射关系,第二次遍历直接通过 map 查找 random 指针的目标。代码逻辑更直观,适合 C++ 环境。

代码实现

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
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;
    
    AddNode(head);
    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++ 版本
class Solution {
public:
    Node* copyRandomList(Node* head) {
        std::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;
            }
            nodeMap[cur] = copytail;
            cur = cur->next;
        }
        
        // 第二次遍历:处理 random 指针
        cur = head;
        Node* copy = copyhead;
        while(cur) {
            if(cur->random == nullptr) {
                copy->random = nullptr;
            } else {
                copy->random = nodeMap[cur->random];
            }
            cur = cur->next;
            copy = copy->next;
        }
        return copyhead;
    }
};

目录

  1. 环形链表
  2. 题目描述
  3. 思路分析
  4. 代码实现
  5. 两个数组中的交集
  6. 题目描述
  7. 思路分析
  8. 代码实现
  9. 随机链表的复制
  10. 题目描述
  11. 思路分析
  12. 代码实现
  13. C 语言版本
  14. C++ 版本
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 知网 AIGC 检测算法升级规则解读及应对策略
  • OpenClaw 龙虾机器人本地部署与配置指南
  • 2025 0xGame Web 方向题目全解
  • 2026年RAG技术演进:DeepSeek与Neo4j构建企业智能体系
  • 开源 AI 短剧工具:从小说到视频的多 Agent 协作流程
  • OpenClaw 本地部署教程:环境配置、插件开发与常见问题排查
  • Cookie 与 Session:Web 用户状态管理详解
  • OpenClaw 环境搭建指南——Windows/macOS/Linux 三平台部署
  • 强化学习核心:Exploit and Explore 策略与多臂老虎机算法
  • 大模型工作岗位解析与项目经理职责详解
  • OpenClaw 厂商全对比:主流 AI 智能体平台深度横评
  • C++ 继承机制详解:派生类函数、虚继承与菱形继承案例
  • CCF-GESP 2025 年 9 月 C++ 三级真题解析
  • AIGC 新兴领域发展与 99 个 AI 专业名词解释
  • AI 编程工具深度对比:Cursor、Copilot、Trae 与 Claude Code
  • 夸克网盘精选资源合集:书籍、软件、教程及 AI 资料
  • MySQL ON DUPLICATE KEY UPDATE 实现存在更新不存在插入
  • 大模型全解析:定义、分类及主流应用案例
  • Coze 专属 AI 应用开发:从智能体构建到 Web 部署指南
  • 为什么顶级团队开始重押 Harness Engineering?AI Agent 时代的底层答案来了

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online