题目内容
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
题目分析
这道题目乍一看可能难度不大,但是真正写起来就会发现,当我按照输入链表的顺序,从头到尾复制了一个新的链表,开始从头处理特殊指针的时候,如何找到当前结点的特殊指针,即定义里面的random
指向的结点在新复制的链表里的位置。如果用暴力破解方法每次都做一个遍历查找,那么时间很容易就变成了
O
(
n
2
)
O(n^2)
O(n2)。所以最好能建立一个映射关系,即访问输入链表的某一结点,能在
O
(
1
)
O(1)
O(1)的时间上找到复制链表对应的结点。
解题
利用map
C++的map能为两个变量直接建立关系,即map<key, value>
。并且能够通过key直接访问value,如map[key] = value;
代码
/*
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 == NULL)
return NULL;
map<RandomListNode*, RandomListNode*> mp;
RandomListNode* currNode = pHead;
while(currNode != NULL){
mp[currNode] = new RandomListNode(currNode->label);
currNode = currNode->next;
}
currNode = pHead;
while(currNode != NULL){
if(currNode->next != NULL)
mp[currNode]->next = mp[currNode->next];
if(currNode->random != NULL)
mp[currNode]->random = mp[currNode->random];
currNode = currNode->next;
}
return mp[pHead];
}
};
另一种解法
这种解法不借助任何STL工具,仅使用数据结构和算法来完成,主要思路分为三步:
- 第一次遍历输入链表,复制得到结点且将其插入到当前结点的next位置;
- 第二次遍历上一步得到的链表,当前结点的复制结点的random指针指向的位置为当前的结点的random指针指向位置得复制结点;
- 第三次遍历上一步得到的链表,拆分为输入链表和输入链表。
如果文字理解不方便,可以看图示,用{A,B,C}表示输入链表的结点,用{A’,B’,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 == NULL)
return NULL;
RandomListNode* currNode = pHead;
while(currNode != NULL){
RandomListNode* newNode = new RandomListNode(currNode->label);
newNode->next = currNode->next;
currNode->next = newNode;
currNode = newNode->next;
}
currNode = pHead;
while(currNode != NULL){
RandomListNode* copyNode = currNode->next;
if(currNode->random != NULL)
copyNode->random = currNode->random->next;
currNode = copyNode->next;
}
RandomListNode* newHead = pHead->next;
currNode = pHead;
while(currNode != NULL){
RandomListNode* copyNode = currNode->next;
currNode->next = copyNode->next;
currNode = currNode->next;
if(currNode != NULL)
copyNode->next = currNode->next;
}
return newHead;
}
};
以上思路为个人想法和网络各位大佬的题解的结合,欢迎讨论与指正。