算法学习17-复制含有随机指针节点的链表(深度拷贝)

复制含有随机指针节点的链表

【题目】一种特殊的链表节点类描述如下:

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
发布了27 篇原创文章 · 获赞 1 · 访问量 1031

猜你喜欢

转载自blog.csdn.net/qq_45205390/article/details/104171541
今日推荐