题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
C++
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
/* 三步法 */
RandomListNode* Clone(RandomListNode* pHead)
{
if (!pHead)
return nullptr;
RandomListNode* pNode = pHead;
// 复制原始链表的任一节点并链接到该节点的后边
while (pNode)
{
RandomListNode* pTemp = new RandomListNode(pNode->label);
pTemp->next = pNode->next;
pNode->next = pTemp;
pNode = pTemp->next;
}
// 初始化复制节点的random关系
pNode = pHead;
while (pNode)
{
RandomListNode* pTemp = pNode->next;
if(pNode->random)
pTemp->random = pNode->random->next;
pNode = pTemp->next;
}
// 从链表中拆分出新链表
RandomListNode* pCopyHead = pHead->next;
RandomListNode* pCopyNode= pHead->next;
pNode = pHead;
while (pNode)
{
pNode->next = pCopyNode->next;
if(pNode->next)
pCopyNode->next = pNode->next->next;
pNode = pNode->next;
pCopyNode = pCopyNode->next;
}
return pCopyHead;
}
/* Hash表法 */
RandomListNode* Clone2(RandomListNode* pHead)
{
if (!pHead)
return nullptr;
map<RandomListNode*, RandomListNode*> nodeMap;
RandomListNode* pNode = pHead;
/* 创建结点 */
while (pNode)
{
RandomListNode* pTemp = new RandomListNode(pNode->label);
nodeMap[pNode] = pTemp;
pNode = pNode->next;
}
pNode = pHead;
/* 创建连接关系 */
while (pNode)
{
RandomListNode* pTemp = nodeMap[pNode];
pTemp->next = nodeMap[pNode->next];
pTemp->random = nodeMap[pNode->random];
pNode = pNode->next;
}
return nodeMap[pHead];
}
};
java
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
import java.util.HashMap;
import java.util.Map;
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
if (pHead == null) {
return null;
}
RandomListNode pHead1 = pHead;
RandomListNode pHead2 = new RandomListNode(pHead.label);
RandomListNode newHead = pHead2;
Map<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
map.put(pHead1, pHead2);
while (pHead1 != null) {
if (pHead1.next != null) {
pHead2.next = new RandomListNode(pHead1.next.label);
} else {
pHead2.next = null;
}
pHead1 = pHead1.next;
pHead2 = pHead2.next;
map.put(pHead1, pHead2);
}
pHead1 = pHead;
pHead2 = newHead;
while (pHead1 != null) {
pHead2.random = map.get(pHead1.random);
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return newHead;
}
}
python
# -*- coding:utf-8 -*-
# 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
head = pHead
p_head = None
new_head = None
#头结点
random_dic = {}
old_new_dic = {}
while head:
node = RandomListNode(head.label)
#这道题还有一个要求就是不能用节点引用,一定要创建新的节点
#复制原节点的label到新的链表中
node.random = head.random
#复制原节点的随机指针到新的链表中
old_new_dic[id(head)] = id(node)
#创建字典,以原节点的内存地址作为key,新节点的内存地址作为value
random_dic[id(node)] = node
#创建另一个字典,以新节点的地址作为key,新节点作为value
head = head.next
#将head指向下一个节点
if new_head:
new_head.next = node
new_head = new_head.next
#给新链表
else:
new_head = node
p_head = node
#当新链表为空时,为新链表的头结点赋值,这里比较巧妙的就是phead可以作为头结点,而new_head可以放心
#向后移动
new_head = p_head
while new_head:
if new_head.random != None:
new_head.random = random_dic[old_new_dic[id(new_head.random)]]
#这里的问题就是old_new_dic中就没有id(new_head.random])的键,
#因为old_new_dic中的键是原节点的地址,但是这里以新节点的随机节点指针指向了
#一个随机的节点,这样的话,随机节点也是原节点中的,因此,这根据随机节点找到对应的新节点的内存地址了,
#然后通过random_dic就找到了新节点了
new_head = new_head.next
#这个循环的目的就是找到new_head的random属性
#现在又出现一个问题,在上边,不是已经把head.random赋给了new_head.random吗?
#那么进一步推理,存在一种可能,那就是前边并没有给new_head赋予属性random
return p_head