leetcode 138. Copy List with Random Pointer

来源:互联网 发布:做生日快乐的软件 编辑:程序博客网 时间:2024/06/05 11:44

Description:
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

加上了一个随机指针的链表,随机指针会随机地指向链表中的任意一个节点或者NULL,要求实现深拷贝。

Solution:
一开始理解错题意了,以为random指针还是直接指向原来的地址即可,后面细细一想,发现并没有那么简单。
这题也出现在《剑指offer》这本书上,看了解法之后越来越觉得这是一个好题,经典题,此题有三种解法,从坏到好一一细说:
Ⅰ超级暴力法。
1、其实难点就是在于我们不知道random指针指向的是哪个节点,既然不知道,那么我们就逐一遍历找到它指向的是第几个节点;
2、在深拷贝时,我们先实现好基本不包括random指针的链表;
3、之后在对原链表进行遍历找出每个的random指针指向的是第几个节点,然后找到新链表对应的下标节点,即可。
时间复杂度为O(n²),空间复杂度为O(1)

Ⅱ map实现(哈希表)
1、我们其实不需要random指向的是第几个节点,我们只需要建立好一个新节点与旧节点的一一对应关系即可;
2、建立好了之后,我们通过random指向的旧节点和map对应关系就能知道新节点的地方。
时间复杂度为O(n),空间复杂度为O(n)

Ⅲ O(1)空间复杂度实现
假如原链表表示为A(C)->B(A)->C(A)->NULL,括号里表示为随机指向的节点;
1、我们先将链表拷贝成如此:
A(C)->A’->B(A)->B’->C(A)->C’->NULL
即将旧链表的每一个节点的next指针指向新链表对应节点,换句话说,就是将新链表间隔地插入旧链表中。

2、拷贝random指针,执行了第一步之后,我们需要找random指针就好找许多,如下:

oldnode->next->random=oldnode->random->next

完成拷贝之后链表如下:
A(C)->A’(C’)->B(A)->B’(A’)->C(A)->C’(A’)->NULL

3、将新链表和旧链表分离即可,得到两个链表:
A(C)->B(A)->C(A)->NULL
A’(C’)->B’(A’)->C’(A’)->NULL

如此做的做法时间复杂度为O(n),空间复杂度为O(1)

Code:
Ⅱ:

class Solution {public:    RandomListNode *copyRandomList(RandomListNode *head) {        map<RandomListNode*, RandomListNode*> newold;        RandomListNode* oldtemp = head;        if (head == NULL)            return head;        RandomListNode* pre = NULL;        RandomListNode* newhead = NULL;        while (head)        {            RandomListNode* cur = new RandomListNode(head->label);            newold[head] = cur;//build a relationship between new nodes and old nodes            if (pre)                pre->next = cur;            else                newhead = cur;            pre = cur;            head = head->next;        }        while (oldtemp)        {            newold[oldtemp]->random=newold[oldtemp->random];            oldtemp=oldtemp->next;        }        return newhead;    }};

Ⅲ:

class Solution {public:    RandomListNode *copyRandomList(RandomListNode *head) {        RandomListNode* temp=head;        if(!head)            return head;        while(temp)        {            RandomListNode* align=new RandomListNode(temp->label);            align->next=temp->next;            temp->next=align;            temp=align->next;        }//the first step        temp=head;        while(temp)        {            if(temp->random)                temp->next->random=temp->random->next;            temp=temp->next->next;        }//the second step        temp=head;        RandomListNode* ans=temp->next;        while(temp)        {            RandomListNode* al=temp->next;            temp->next=al->next;            temp=al->next;            if(al->next)                al->next=al->next->next;        }//split new link and old link        return ans;    }};
0 0
原创粉丝点击