复制含有随机指针节点的链表
【题目】一种特殊的链表节点类描述如下:
java结构如下
public class Node{
public intvalue;
public Nodenext;
public Noderand;
public Node(intdata){
this.value=data;
}
c++结构如下
struct Node
{
int value;
Node *next;
Node *rand;
};
Node类中的value是节点值,next指针和正常单链表中next指针的意义一样,都指向下一个节点,rand指针是Node类中新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的头节点。进阶:不使用额外的数据结构,只用有限几个变量,且在时间复杂度为O(N)内完成原问题要实现的函数。
(RandomListNode类中的label是节点值,next指针和正常的单链表指针中的next指针的意义一样,都指向下一个节点,random指针是RandomListNode类中的新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向NULL。给定一个由RandomListNode节点类型组成的五环单链表的头节点pHead,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的头节点)。
图解算法
普通解法
可以做到时间复杂度为O(N),空间复杂度为O(N)。
代码实现
#include <iostream>
#include <hash_map>
using namespace std;
using namespace __gnu_cxx;
struct Node
{
int value;
Node *next;
Node *rand;
};
//使用hash_map所需要的hash函数
struct hash_Node
{
size_t operator() (const Node &node) const
{
return node.value;
}
};
//使用hash_map所需要的比较函数
struct compare_Node
{
bool operator() (const Node &n1,const Node &n2) const
{
return n1.value == n2.value && n1.next == n2.next && n1.rand == n2.rand;
}
};
//使用hash_map解决问题
Node* copyListWithRand(Node *head)
{
hash_map<Node,Node,hash_Node,compare_Node> map;
Node *cur = head;
while(NULL != cur)
{
Node *ptr = new Node;
ptr->value = cur->value;
ptr->next = NULL;
ptr->rand = NULL;
map[*cur] = *ptr; //一一对应的关系
cur = cur->next;
}
cur = head;
while(NULL != cur)
{
map[*cur].next = cur->next;
map[*cur].rand = cur->rand;
cur = cur->next;
}
return &map[*head];
}
void printListWithRand(Node *head)
{
while(NULL != head)
{
if(NULL != head->rand)
cout << head->value << " rand is: " << head->rand->value << endl;
else
cout << head->value << " rand is: NULL " << endl;
if(NULL != head->next)
cout << head->value << " next is: " << head->next->value << endl;
else
cout << head->value << " next is: NULL " << endl;
head = head->next;
}
}
int main()
{
Node *head = NULL;
Node *ptr = NULL;
for(int i =0;i<4;i++)//构造链表
{
if(NULL == head)
{
head = new Node;
head->value = i;
head->next = NULL;
head->rand = NULL;
ptr = head;
continue;
}
ptr->next = new Node;
ptr->rand = ptr->next;
ptr = ptr->next;
ptr->value = i;
ptr->next = NULL;
ptr->rand = NULL;
}
cout << "before copy:" << endl;
printListWithRand(head);
cout << "Using hash_map to copy:" << endl;
ptr = copyListWithRand1(head);
printListWithRand(ptr);
return 0;
}
运行结果如下:
before copy:
0 rand is: 1
0 next is: 1
1 rand is: 2
1 next is: 2
2 rand is: 3
2 next is: 3
3 rand is: NULL
3 next is: NULL
Using hash_map to copy:
0 rand is: 1
0 next is: 1
1 rand is: 2
1 next is: 2
2 rand is: 3
2 next is: 3
3 rand is: NULL
3 next is: NULL
进阶算法
不使用额外的数据结构,只用有限的几个变量,且在时间复杂度为O(N)内完成。
#include <iostream>
using namespace std;
Node* copyListWithRand2(Node *head)
{
if(NULL == head)
return NULL;
Node *cur = head;
Node *next = NULL;
while(NULL != cur)
{
next = new Node;
next->value = cur->value;
next->next = cur->next;
next->rand = NULL;
cur->next = next;
cur = next->next;
}
cur = head;
Node *curCopy = NULL;
while(NULL != cur) //复制rand
{
next = cur->next->next;
curCopy = cur->next;
curCopy->rand = NULL != cur->rand ? cur->rand->next : NULL;
cur = next;
}
Node *res = head->next;
cur = head;
while(NULL != cur)
{
next = cur->next->next;
curCopy = cur->next;
cur->next = next;
curCopy->next = NULL != next ? next->next : NULL;
cur = next;
}
return res;
}
void printListWithRand(Node *head)
{
while(NULL != head)
{
if(NULL != head->rand)
cout << head->value << " rand is: " << head->rand->value << endl;
else
cout << head->value << " rand is: NULL " << endl;
if(NULL != head->next)
cout << head->value << " next is: " << head->next->value << endl;
else
cout << head->value << " next is: NULL " << endl;
head = head->next;
}
}
int main()
{
Node *head = NULL;
Node *ptr = NULL;
for(int i =0;i<4;i++)//构造链表
{
if(NULL == head)
{
head = new Node;
head->value = i;
head->next = NULL;
head->rand = NULL;
ptr = head;
continue;
}
ptr->next = new Node;
ptr->rand = ptr->next;
ptr = ptr->next;
ptr->value = i;
ptr->next = NULL;
ptr->rand = NULL;
}
cout << "before copy:" << endl;
printListWithRand(head);
cout << "Using advanced algorithm to copy:" << endl;
ptr = copyListWithRand2(head);
printListWithRand(ptr);
return 0;
}
运行结果如下
before copy:
0 rand is: 1
0 next is: 1
1 rand is: 2
1 next is: 2
2 rand is: 3
2 next is: 3
3 rand is: NULL
3 next is: NULL
Using advanced algorithm to copy:
0 rand is: 1
0 next is: 1
1 rand is: 2
1 next is: 2
2 rand is: 3
2 next is: 3
3 rand is: NULL
3 next is: NULL