func copyRandomList(head *Node) *Node {
if head == nil {
return head
}
//复制Next节点
cur := head
for cur != nil {
next := cur.Next
cur.Next = &Node{Val: cur.Val}
cur.Next.Next = next
cur = next
}
//复制Random节点
cur = head
for cur != nil {
curNew := cur.Next
if cur.Random != nil {
//新链表节点的 random 指针指向旧链表对应节点的 random 指针的下一个值
curNew.Random = cur.Random.Next
}
cur = cur.Next.Next
}
//把原链表的复制Next节点,复制Random节点, 断开连接关系
headNew := head.Next
cur = head
curNew := head.Next
for cur != nil {
cur.Next = cur.Next.Next
cur = cur.Next
if cur == nil {
curNew.Next = nil
} else {
curNew.Next = cur.Next
}
curNew = curNew.Next
}
return headNew
}
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
HashMap={}
for p in [head]:
while p:
if p not in HashMap:
HashMap[p]=Node(p.val)
p=p.next
for p in [head]:
while p:
if p.next:
HashMap[p].next=HashMap[p.next]
if p.random:
HashMap[p].random=HashMap[p.random]
p=p.next
return HashMap.get(head)
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head:
return None
# 复制&合并
cur = head
while cur:
nxt = cur.next
cur.next = Node(cur.val)
cur.next.next = nxt
cur = nxt
# 复制random node
cur = head
while cur:
new_cur = cur.next
new_cur.random = cur.random.next if cur.random else None
cur = cur.next.next
# 拆分
res = head.next
cur = head
new_cur = head.next
while cur:
nxt = cur.next
cur.next = cur.next.next
cur = cur.next
new_cur.next = cur.next if cur else None
new_cur = new_cur.next
return res
共以下 62 个回答
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
}
*/
class Solution {
public Node copyRandomList(Node head) {
if(head null) return null;
Node tmp = head;
while(tmp!=null){
Node next = tmp.next;
tmp.next = new Node(tmp.val);
tmp.next.next = next;
tmp = next;
}
tmp = head;
while(tmp!=null){
Node next = tmp.next;
tmp.next.random = tmp.randomnull?null:tmp.random.next;
tmp = tmp.next.next ;
}
}
先复制原节点顺序,再复制random顺序,再拆分
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public Node copyRandomList(Node head) {
if(head null){
return null;
}
//复制节点
Node cur = head;
while(cur != null){
Node tmp = new Node(cur.val);
tmp.next = cur.next;
cur.next = tmp;
cur = tmp.next;
}
}
时间复杂度:O(n)
空间复杂度:O(1)
时间复杂度O(n)
空间复杂度O(n)
时间复杂度o(n)
空间复杂度o(n)
时间复杂度o(n) 空间复杂度o(n)
代码
“`java
class Solution{
public Node copyRandomList(Node head){
if(head == null){
return null;
}
Node cur = head;
while(cur! = null){
Node next = cur.next;
cur.next= new Node(cur.val);
cur.next.next=next;
cur = next;
}
//复制随机节点
cur = head;
while(cur!= null){
Node curNew = cur.next;
curNew.random = cur.random == null? null : cur.random.next;
cur = cur.next.next;
}
//拆分,比如把A->A1->B->B1->C->C1拆分成A->B->C和A1->B1->C1
Node headNew = head.next;
cur = head;
Node curNew = head.next;
while(cur! = null){
cur.next= cur.next.next;
cur=cur.next;
curNew . next = cur == null? null: cur.next;
curNew = curNew.next;
}
return headNew;
}
}
复制,分离
时间复杂度O(n) 空间复杂度O(1)
代码:
思路:
通过字典映射,将原本的链表和新链表对应起来。第一次遍历生成新链表(未连接,只赋值),第二次遍历连接新链表。
时间:遍历两次链表,O(n)
空间:用了大小为链表长度的辅助字典,O(n)
时间复杂度:O(n) 空间复杂度:O(n)
打卡
时间复杂度:O(n)。
额外空间复杂度:O(1)。
构建hash表,时间复杂度O(n)空间复杂度O(n)
拆分链表
【思路】这题比较容易出错,通过先复制后拆分的方法完成,共需要三次遍历链表
【复杂度】时间O(n),空间O(1)
没写出来,看了思路,这题直接在原地复制节点的思想很赞
时间复杂度O(n)
空间复杂度O(1)
//注意空引用的问题 若next为null,则next.next会报错
“`java maps = new HashMap<>();
public Node copyRandomList(Node head) {
if (head == null) {
return head;
}
Node current = head;
Map
//复制全部节点
while (current != null) {
//本体为key,复制的分身为value
maps.put(current, new Node(current.val));
current = current.next;
}
//处理每个节点的next和random
current = head;//从头开始
while (current != null) {
//当前节点的分身的next指向原节点的next的分身
maps.get(current).next = maps.get(current.next);
//当前节点的分身的random指向原节点的random的分身
maps.get(current).random = maps.get(current.random);
current = current.next;
}
//新链表的分身就是head为key的value
return maps.get(head);
“`java
时间复杂度O(n),空间复杂度O(n)
“`Java
class Solution {
public Node copyRandomList(Node head) {
if(head null){
return null;
}
// 复制链表节点
Node cur = head;
while(cur != null){
Node next = cur.next;
cur.next = new Node(cur.val);
cur.next.next = next;
cur = next;
}
// 复制随机节点
cur = head;
while(cur != null){
Node curNew = cur.next;
curNew.random = cur.random null ? null : cur.random.next;
cur = cur.next.next;
}
Node headNew = head.next;
cur = head;
Node curNew = head.next;
while(cur != null){
cur.next = cur.next.next;
cur = cur.next;
curNew.next = cur null ? null : cur.next;
curNew = curNew.next;
}
}
“`c++ m;
class Solution {
public:
Node* copyRandomList(Node* head) {
// 用map快速查询next和random指向的节点
unordered_map
// 先对值进行拷贝
for(Node* cur = head;cur;cur=cur->next){
m[cur] = new Node(cur->val);
}
// 再对next和random拷贝
for(Node* cur = head;cur;cur=cur->next){
if(cur->next) m[cur]->next = m[cur->next];
if(cur->random) m[cur]->random = m[cur->random];
}
return m[head];
}
};
“`cpp
class Solution{
public:
Node* copyRandomList(Node* head){
if(!head){
return nullptr;
}
// 赋值链表结点
Node* cur = head;
while(cur){
Node* next = cur->next;
cur->next = new Node(cur->val);
cur->next->next = next;
cur = next;
}
// 复制随机结点
cur = head;
while(cur){
Node* curNew = cur->next;
curNew->random = cur->random ? cur->random->next : nullptr;
cur = cur->next->next;
}
// 拆分,比如把A->A1->B->B1->C->C1 拆分成 A->B->C 和 A1->B1->C1
Node* headNew = head->next;
cur = head;
Node* curNew = head->next;
while(cur){
cur->next = cur->next->next;
cur = cur->next;
curNew->next = cur ? cur->next : nullptr;
curNew = curNew->next;
}
return headNew;
}
}
时间复杂度O(n),空间复杂度O(n)
cpp,不会,看的题解
unordered_map<Node,Node>cacheNode;
Node* copyRandomList(Node* head) {
if(headNULL)
{
return head;
}
if(!cacheNode.count(head))
{
Node* headNew = new Node(head->val);
cacheNode[head] = headNew;
headNew->next = copyRandomList(head->next);
headNew->random = copyRandomList(head->random);
}
return cacheNode[head];
}
“`c++
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) {
return nullptr;
}
// 复制链表节点
Node* cur = head;
while (cur) {
Node* next = cur->next;
cur->next = new Node(cur->val);
cur->next->next = next;
cur = next;
}
}
};
“`
用哈希来实现的,空间复杂度相对于原地复制要高,但是好理解
1、在遍历原链表的同时创建对应的新节点插入哈希表进行匹配;
2、遍历完成后哈希表中原链表节点映射的新节点串联起来;
3、最后返回哈希表中存储的原链表的头节点
复制并拆分
哈希
C++
两个解法,第一个较为方便,但是O(n)空间,第二个O(1)空间
解法1: 使用hashMap,先复制所有的节点,再复制所有节点的next和random
TC: O(n)
SC: O(n)
“`c++mp;
class Solution {
public:
Node* copyRandomList(Node* head) {
unordered_map
Node* curr = head;
while (curr) {
mp[curr] = new Node(curr->val);
curr = curr->next;
}
curr = head;
while (curr) {
mp[curr]->next = mp[curr->next];
mp[curr]->random = mp[curr->random];
curr = curr->next;
}
return mp[head];
}
};
遍历+map:两次遍历,第一次遍历创建链表所有节点,并且把新链表与旧链表的每个节点用map对应起来;第二次遍历依靠map创建新链表中每个节点的random。
时间:O(n)
空间:O(n)
思路:遍历链表,依次生成节点嵌入哈希表中,然后再次遍历,生成各个节点间的链接
时间复杂度:O(n), 空间复杂度O(n)
【时间O(n),空间O(n)】
先复制next指针,同时存储两个链表节点的对应关系
然后复制rand指针
时间复杂度:O(n)
空间复杂度:O(1)
1、判空,复制链表节点
2、复制随机节点
3、拆分,比如把 A->A1->B->B1->C->C1拆分成 A->B->C和A1->B1->C1
时间复杂度 O(n) 空间复杂度 O(n)
首先必须做两遍遍历,因为第一遍的时候random所指节点可能还没有建出来。第一遍遍历能填充全部的 val 和 next
第二遍遍历的时候填充random,参考p的random指针,所以在这之前可以建立一个新链表和旧链表之间节点的对应
思路:
首先是复制节点,然后复制节点的random指针(将原节点的random指针指向的节点的下一个节点赋值给原节点的下一个节点(复制节点)的random指针),后将链表拆分,返回深拷贝后的头指针即可。
困难
可以
哈希映射
class Solution {
public:
Node* copyRandomList(Node* head) {
if (head nullptr) return nullptr;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
C++:复制加拆分(第一次接触
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head NULL) return head;
Node* cur = head;
//复制节点
while(cur){
Node* next = cur->next;
cur->next = new Node(cur->val);
cur->next->next = next;
cur = next;
}
//复制随机节点
cur = head;
while(cur){
//Node* curNew = cur->next;
//curNew->random = cur->random NULL ? NULL : cur->random->next;
cur->next->random = cur->random NULL ? NULL : cur->random->next;
cur = cur->next->next;
}
//拆分节点
Node* headnew = head->next;
cur = head;
Node* curnew = cur->next;
while(cur){
cur->next = cur->next->next;
cur = cur->next;
curnew->next = cur NULL ? NULL : cur->next;
curnew = curnew->next;
}
return headnew;
};
class Solution {
public Node copyRandomList(Node head) {
if(headnull){
return null;
}
}
java实现
只能说理解起来不难,但太容易出错了!
原地反转还是好难理解……
这里是Ming的打卡:
多多注意空指针情况,考虑随机结点是否为空再去走下一步
js实现
var copyRandomList = function(head) {
if(head=null){
return null;
}
let cur=head;
let map=new Map();
while(cur!null){
map.set(cur,new Node(cur.val,null,null));
cur=cur.next;
}
cur=head;
while(cur!null){
map.get(cur).next=map.get(cur.next)??null;
map.get(cur).random=map.get(cur.random)?? map.get(cur.random);
cur=cur.next;
}
return map.get(head);
};
思路:
1、复制节点的值,将新复制的节点的值直接放在原有节点的后面
2、复制random指针部分,由于新复制的节点在原来节点的后面,那么复制后的random指针所指的就是原来random指针所指的后一个节点。
3、拆分链表
“`c++
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head){
return NULL;
}
// 1、复制节点的值,将新复制的节点的值直接放在原有节点的后面
Node* cur = head;
while(cur){
Node* newcur = new Node(0);
newcur->val = cur->val;
newcur->next = cur->next;
cur->next = newcur;
cur = newcur->next;
}
// 2、复制random指针部分
cur = head;
while(cur){
if(cur->random){
cur->next->random = cur->random->next;
}
cur = cur->next->next;
}
// 3、拆分链表
cur = head;
Node* newHead = head->next; // 记录拆分后的复制出来的新链表的头指针
Node* temp = nullptr;
while(cur->next){
temp = cur->next;
cur->next = temp->next;
cur = temp;
}
return newHead;
}
};
思路
代码
class Solution{
public Node copyRamdomList(Node head){
if(headnull){
return null;
}
Node cur=head;
while(cur!=null){
Node.next=cur.next;
cur.next=new Node(cur.val);
cur.next.next=next;
cur=next;
}
cur=head;
while(cur!=null){
Node curNew=cur.next;
curNew.random=cur.randomnull?null:cur.random.next;
cur=cur.next.next;
}
Node headNew=head.next;
cur=head;
Node curNew=head.next;
while(cur!=null){
cur.next=cur.next.next;
cur=cur.next;
curNew.next=curnull?null:cur.next;
curNew=curNew.next;
}
return headNew;
}
}
时间复杂度:O(n)
额外空间复杂度:O(1)