您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 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;
}
nullptr
node->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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。