class RandomListNode:
def __init__(self, x):
self.label = x
self.next = None
self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
#空节点直接返回
if pHead is None:
return pHead
#添加一个头部节点
cur = pHead
#遍历原始链表,开始复制
while cur is not None:
#拷贝节点
clone = RandomListNode(cur.label)
#将新节点插入到被拷贝的节点后
clone.next = cur.next # 当前指向下一节点的指针 变成 拷贝后节点指向下一节点的指针
cur.next = clone # 当前指向下一节点的位置是拷贝后的节点
cur = clone.next # 遍历的第一个节点
cur = pHead
clone = pHead.next
res = pHead.next
#连接新链表的random节点;二次遍历
while cur is not None:
#跟随前一个连接random
if cur.random is None:
clone.random = None
#后一个节点才是拷贝的
else:
clone.random = cur.random.next # 图
#cur.next必定不为空
cur = cur.next.next
#检查末尾节点
if clone.next is not None:
clone = clone.next.next
cur = pHead
clone = pHead.next
#拆分两个链表
while cur is not None:
#cur.next必定不为空
cur.next = cur.next.next
cur = cur.next
#检查末尾节点
if clone.next is not None:
clone.next = clone.next.next
clone = clone.next
return res
时间复杂度On,第一次遍历n,第二次和第三次是2n
空间复杂度O1
def copyRandomList(head: 'Node') -> 'Node':
'''
第一步:现将每个节点进行copy,并连接在当前节点后:a-b-c复制为a-a'-b-b'-c-c'
第二步:copy原节点的random值
第三步:拆分链表
Args:
head:
Returns:
'''
if not head:
return head
cur = head
# 第一轮copy值和next
while cur:
after = cur.next
new_cur = Node(cur.val)
cur.next = new_cur
cur.next.next = after
cur = after
# 第二轮copy节点的随机数
cur = head
while cur:
new = cur.next
new.random = None if cur.random == None else cur.random.next
cur = cur.next.next
# 第三轮将经过复制后的链表进行拆分
# a-a'-b-b'c-c'
# 拆分为a-b-c,和a'-b'-c'
cur = head
copy_cur = head.next
head_cur = head.next
while cur:
cur.next = copy_cur.next
cur = cur.next
# 这里注意cur为空的情况
copy_cur.next = cur.next if cur != None else None
copy_cur = copy_cur.next
return head_cur
class Solution(object):
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
if not head:
cur = head
return cur
# 复制链表节点
cur = head
while cur :
newnode = Node(cur.val)
newnode.next = cur.next
cur.next = newnode
cur = newnode.next
# 复制链表节点的随机指针
cur = head
while cur:
if cur.random:
cur.next.random = cur.random.next
cur = cur.next.next
#拆分链表,new代表新链表,old代表原链表
res = head.next
new = res
old = head
while new.next:
old.next = old.next.next
new.next = new.next.next
old = old.next
new = new.next
# 单独处理原链表末尾节点
old.next = None
return res
class Solution(object):
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
if not head:
return None
# 1. 复制节点
cur = head
while cur:
copy = Node(cur.val)
copy.next = cur.next
cur.next = copy
cur = copy.next
# 2. 复制random
cur = head
while cur:
if cur.random:
cur.next.random = cur.random.next
cur = cur.next.next
# 3. 拆分链表
cur = head
new = head.next
while cur.next:
tmp = cur.next
cur.next = tmp.next
cur = tmp
return new
时间复杂度:O(n)
空间复杂度:O(1)
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
res_dict = {}
cur = head
while cur:
res_dict[cur] = Node(cur.val)
cur = cur.next
cur = head
while cur:
res_dict[cur].next = res_dict.get(cur.next)
res_dict[cur].random = res_dict.get(cur.random)
cur = cur.next
return res_dict.get(head)
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head:
return None
# 在每个节点后面创建新的节点
p = head
while p:
new_node = Node(p.val,None,None)
new_node.next = p.next
p.next = new_node
p = new_node.next
# 设置新节点的随机节点
p = head
while p:
if p.random:
p.next.random = p.random.next
p = p.next.next
# 拆分链表为原链表和新链表
dummy = Node(-1)
p = head
curr = dummy
while p:
curr.next = p.next
curr = curr.next
p.next = curr.next
p = p.next
return dummy.next
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head:
return None
#复制节点
f = head
while f :
x = Node(f.val)
x.next = f.next
f.next = x
f = x.next
#复制random
f = head
while f :
f.next.random = f.random.next if f.random else None
f = f.next.next
#拆分
l1 = l2 = head.next
pre = head
while l1.next :
pre.next = pre.next.next
l1.next = l1.next.next
pre = pre.next
l1 = l1.next
pre.next = None
return l2
func copyRandomList(head *Node) *Node {
// 要实际复制,不然可以检测出来
// return head
if head == nil {
return head
}
cur := head
// 复制链表结点
for cur != nil {
next := cur.Next
cur.Next = &Node{
Val: cur.Val,
Next: nil,
Random: nil,
}
cur.Next.Next = next
cur = next
}
// 复制随机结点
cur = head
for cur != nil {
curNew := cur.Next
if cur.Random != nil {
curNew.Random = cur.Random.Next
} else {
curNew.Random = nil
}
cur = cur.Next.Next
}
// 拆分成两个链表
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 Node:
def __init__(self, x, next=None, random=None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution(object):
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
if not head:
return head
dir = {}
cur = head
while cur != None:
dir[cur] = Node(cur.val)
cur = cur.next
cur = head
while cur != None:
dir[cur].next = dir.get(cur.next)
dir[cur].random = dir.get(cur.random)
cur = cur.next
return dir[head]
class Solution {
public Node copyRandomList(Node head) {
if (head == null) {
return head;
}
//map中存的是(原节点,拷贝节点)的一个映射
Map<Node, Node> map = new HashMap<>();
for (Node cur = head; cur != null; cur = cur.next) {
map.put(cur, new Node(cur.val));
}
//将拷贝的新的节点组织成一个链表
for (Node cur = head; cur != null; cur = cur.next) {
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
}
return map.get(head);
}
}
共以下 69 个回答
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
}
*/
class Solution {
public Node copyRandomList(Node head) {
if (head null) return null;
}
“`c++
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head)
return NULL;
};
”’
时间复杂度:O(n)
空间复杂度:O(1)【注意没有额外辅助空间,创建链表的空间是必须要的,不是额外的】
#时间复杂度o(N)
#空间复杂度o(1)
“`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;
}
}
}
“`java
#时间复杂度o(N)
#空间复杂度o(1)
“`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;
}
while(cur!=null){
cur.next=cur.next.next;
cur=cur.next;
curNew.next=curnull? null:cur.next;
curNew=curNew.next;
}
}
}
“`java
这题做了好几遍,深入理解了双链表
复制+拆分
解法一:哈希
①由于随机指针的存在,当拷贝节点时,当前节点的随机指向的节点可能还没创建,因此用哈希表记录每一个节点对应的新节点
②先不考虑random指针,和原本的链表复制一样,创建新节点,并构造next指针关系,同时使用哈希表记录原节点和新节点的映射关系
③对原链表和新链表进行同时遍历,对于原链表的每个节点上的random都通过哈希表找到对应的新的random节点,并在新链表上构造random关系
● 时间复杂度:O(n)
● 空间复杂度:O(n)
解法二:复制+拆分
思路:
①在原链表每一个节点后,复制一下节点,再为每一个新节点的random属性赋值
②将当前链表,按照一个间隔一个的顺序拆分开,将新节点,串成一个新链表,将原链表的节点,拆出来并组合成原链表
③将 原链表的最后一个节点的next指针,重新指向null
● 时间复杂度:O(n)
● 空间复杂度:O(1)
时间复杂度: O(n)
空间复杂度: O(1)
迭代拆分
时间复杂度:O(n)
空间复杂度:O(1)
方法一:原地复制拆分
1. 时间复杂度:O(n)
2. 空间复杂度:O(1)
3. 代码
复杂度分析:
时间复杂度:O(n),空间复杂度O(1)
借助hash表进行节点的映射
哈希表
拼接加拆分
时间复杂度:O(n)
空间复杂度:O(1) (返回值不计入)
两次迭代遍历+哈希表,看了下题解,用递归可能跟简单一点
将复制的节点插入原节点后面,即a->b->c => a->a’->b->b’->c->c’
可以在O(1)时间复杂度找到新链表的random节点,即 a’.random=a.random.next,最后要恢复原链表
时间O(n) 空间O(1)
时间复杂度O(N)
空间复杂度O(N)
先进行原地复制,通过遍历对随机节点进行复制,过程中注意空节点的判断,之后将链表拆分成两条链表。时间复杂度O(n),空间复杂度O(n)
思路:
1. 若头节点 head 为空节点,直接返回 null ;
2. 初始化一个HashMap map, 指针cur 指向头节点;
3. 复制链表:
1)建立新节点,并向 map集合中 添加键值对 (原 cur 节点, 新 cur 节点) ;
2)cur 遍历至原链表下一节点;
4. 构建新链表的引用指向:
1)构建新节点的 next 和 random 引用指向;
2)cur 遍历至原链表下一节点;
5. 返回值: 新链表的头节点 map[cur] ;
时间复杂度O(n)
空间复杂度O(n)
将复杂问题分步完成:先创建每个节点的复制节点,然后再对每个节点的 random 进行复制,最后隔一拿一拆链。
注意要区 cur->next 的时候一定要先对 cur 进行空指针判断,同时合理使用 cur 和 使用 cur->next 做为判断条件。
时间复杂度O(n)
空间复杂度O(n)
时间复杂度O(n)
空间复杂度O(1)
时间复杂度:O(n)
空间复杂度:O(1)
时间复杂度:O(n)
解法:原地(复制+拆分)
思路:1.对原链表的每个节点进行复制,并追加到原节点的后面 2.复制随机节点 3.拆分
Time:O(N)
Sapce :O(1)
下面代码
时间复杂度O(n)
时间复杂度 O(n)
//使用map
class Solution {
public:
Node* copyRandomList(Node* head) {
unordered_map<Node,Node> map;
Node* cur=head;
Node* dummy=new Node(0);
Node* pre=dummy;
while(cur){
Node* newnode=new Node(cur->val);
map[cur]=newnode;
pre->next=newnode;
pre=pre->next;
cur=cur->next;
}
cur=head;
Node* start=dummy->next;
while(cur){
if(cur->random!=nullptr){
auto it=map.find(cur);
it->second->random=map.find(cur->random)->second;
}
cur=cur->next;
}
return dummy->next;
}
};
时间:O(n)
空间:O(n)
哈希迭代,时空复杂度On
一开始没有考虑head为空的时候
先复制一份链表,然后再拆分(指针部分搞得迷迷糊糊的)
看题解了,先打卡
解体思路:创建新的链表,每个原节点后跟一个复制节点,随后遍历链表让复制节点的random指针指向前一个原节点的random指针的next,随后再拆分链表,得到复制后的结果。
时间复杂度:O(n)
空间复杂度:O(1)
思路一:暴力。用两个Node型的动态数组ArrayList,一个为temp,另一个为res,temp存放原链表的每一个节点,res存放复制过来的每一个节点(节点中next指针域和random指针域都没有赋值),然后遍历res,给res中每一个节点的next指针域和random指针域赋值。时间复杂度O(N),空间复杂度O(N)。
思路二:其实思路一用两个动态数组来存放新的复制链表中random节点与原链表的节点的对应关系。可以用一个哈希结构来替换两个动态数组。时间复杂度O(N),空间复杂度O(N)。
思路三:解决本题的核心就是要知道新链表中每一个节点random节点在新链表的位置。直接在原链表上复制每一个节点在原节点的后面(复制操作),1->2->3复制后为1->1->2->2->3->3。再让新的复制节点的random的指针域指向原节点指针的下一个节点,最后把新链表从原链表拆分出来。(拆分操作)时间复制度O(N),空间复杂度O(1)(返回的结果链表不计入)。
思路四:思路二是哈希+迭代实现。可以用哈希+递归实现。
哈希表记住映射关系,然后先走一遍建立单链表,再串random
额
复制链表并拆分
本题最优的解法是复制链表,进行拆分。复制一个新的节点在原有节点之后,如 1 -> 2 -> 3 -> null 复制完就是 1 -> 1 -> 2 -> 2 -> 3 – > 3 -> null。然后从头开始遍历链表,将复制的链表与随机指针进行串联,前提要进行判断,保证数据是否为空。最后将链表进行拆分,得到了复制的链表。
时间复杂度O(n),空间复杂度O(1);
关键点:p->next->random=p->random->next;
时间复杂度:O(n)
空间复杂度:O(1)
这个题目难在这个理解复制是指的深拷贝
深拷贝意味着每个节点都是新的区别之前地址的存储空间
因此拷贝是需要区分两个过程
第一个过程先单纯的把直线链接链接起来
第二个过程再把random链接起来
看的题解,原本想法是像普通链表一样先建立,random用字典去记住,再遍历一遍新链表的同时给random赋值
时间复杂度O(n)
空间复杂度O(n)
哈希表
之前做过一遍,还是写了挺久
时间复杂度:O(n),空间复杂度O(1)
先用哈希把节点拷贝一份,再在复制的时候从哈希中调
时间空间都是O(n)
时间空间都是O(n),