您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        # C++中怎么利用LeetCode拷贝带有随机指针的链表
## 引言
在数据结构与算法的学习中,链表是最基础也是最重要的数据结构之一。而带有随机指针的链表(通常称为"Random List"或"Copy List with Random Pointer")因其特殊的结构,成为面试和LeetCode中的经典题目。本文将深入探讨如何在C++中高效地解决这个问题。
## 问题描述
### 链表节点定义
```cpp
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = nullptr;
        random = nullptr;
    }
};
给定一个链表的头节点head,每个节点包含:
- val:节点值
- next:指向下一个节点的指针
- random:可能指向链表中任意节点或为nullptr
要求深拷贝这个链表,并返回新链表的头节点。
next和random指针关系#include <unordered_map>
Node* copyRandomList(Node* head) {
    if (!head) return nullptr;
    
    std::unordered_map<Node*, Node*> nodeMap;
    Node* curr = head;
    
    // 第一次遍历:创建节点并建立映射
    while (curr) {
        nodeMap[curr] = new Node(curr->val);
        curr = curr->next;
    }
    
    // 第二次遍历:建立连接关系
    curr = head;
    while (curr) {
        nodeMap[curr]->next = nodeMap[curr->next];
        nodeMap[curr]->random = nodeMap[curr->random];
        curr = curr->next;
    }
    
    return nodeMap[head];
}
random指针原链表:A -> B -> C
交错后:A -> A' -> B -> B' -> C -> C'
Node* copyRandomList(Node* head) {
    if (!head) return nullptr;
    
    // 第一步:插入新节点
    Node* curr = head;
    while (curr) {
        Node* newNode = new Node(curr->val);
        newNode->next = curr->next;
        curr->next = newNode;
        curr = newNode->next;
    }
    
    // 第二步:设置random指针
    curr = head;
    while (curr) {
        if (curr->random) {
            curr->next->random = curr->random->next;
        }
        curr = curr->next->next;
    }
    
    // 第三步:分离链表
    curr = head;
    Node* newHead = head->next;
    Node* copyCurr = newHead;
    
    while (curr) {
        curr->next = curr->next->next;
        if (copyCurr->next) {
            copyCurr->next = copyCurr->next->next;
        }
        curr = curr->next;
        copyCurr = copyCurr->next;
    }
    
    return newHead;
}
nullptrnode->random = node// 测试自循环
Node* testSelfLoop() {
    Node* node = new Node(1);
    node->random = node;
    return copyRandomList(node);
}
// 测试random为null
Node* testNullRandom() {
    Node* head = new Node(1);
    head->next = new Node(2);
    head->next->random = head;
    return copyRandomList(head);
}
| 方法 | 时间复杂度 | 空间复杂度 | 适用场景 | 
|---|---|---|---|
| 哈希表法 | O(n) | O(n) | 通用,代码简洁 | 
| 节点交错法 | O(n) | O(1) | 内存受限环境 | 
浅拷贝问题:直接复制指针而非创建新节点
// 错误示例!
newNode->random = oldNode->random;  // 这是浅拷贝
未处理nullptr:访问random前未检查是否为空
// 危险代码!
nodeMap[curr]->random = nodeMap[curr->random];  // 当random为null时会出错
链表分离错误:在交错法中破坏原链表结构后未能正确恢复
def copyRandomList(self, head: 'Node') -> 'Node':
    if not head: return None
    node_map = {}
    
    # 第一次遍历创建节点
    curr = head
    while curr:
        node_map[curr] = Node(curr.val)
        curr = curr.next
    
    # 第二次遍历建立连接
    curr = head
    while curr:
        node_map[curr].next = node_map.get(curr.next)
        node_map[curr].random = node_map.get(curr.random)
        curr = curr.next
    
    return node_map[head]
本文详细分析了LeetCode 138题”Copy List with Random Pointer”的两种主要解法。哈希表法直观易懂,适合大多数场景;而节点交错法则以巧妙的思路实现了空间优化。理解这两种方法不仅能帮助我们解决这个问题,更能提升对链表和指针操作的整体认知。
掌握这类问题的解法,将大大提升你在面试中对复杂指针问题的处理能力。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。