首页 > 其他 > 详细

LeetCode Copy List with Random Pointer

时间:2014-03-15 05:17:52      阅读:490      评论:0      收藏:0      [点我收藏+]
bubuko.com,布布扣
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if (head == NULL) return NULL;
        unordered_map<RandomListNode*, RandomListNode*> p2p;
        
        RandomListNode* newhead = new RandomListNode(head->label);
        newhead->random = head->random;
        p2p.insert(pair<RandomListNode*, RandomListNode*>(head, newhead));
        
        RandomListNode* tail = newhead;
        head = head->next;
        
        while (head != NULL) {
            RandomListNode* item = new RandomListNode(head->label);
            item->random = head->random;
            p2p.insert(pair<RandomListNode*, RandomListNode*>(head, item));
            
            tail->next = item;
            tail = item;
            head = head->next;
        }
        
        tail = newhead;
        while (tail != NULL) {
            if (tail->random != NULL) {
                tail->random = p2p.find(tail->random)->second;
            }
            tail = tail->next;
        }
        return newhead;
    }
};
bubuko.com,布布扣

因为random指针的指向是随机的,自己没想出什么不用map的方法。map存储的是旧对象地址(key)-相应的新对象的地址(value)。这样在第一次遍历原链表时进行链表复制,并对每个对象建立旧地址到新地址的映射,暂时直接复制random字段的值。然后进行第二次链表遍历,这回是对刚刚建立的新链表,如果发现其random字段不为NULL,则它存储了一个对象的旧地址值,因为我们已经有了所有对象的旧-新地址映射表,所以很方便的能够查找到该指针指向的对象的新地址值。这样链表的深拷贝就完成了。

  • unordered_map 无序的,hash实现,O(1),C++11中才有,要加编译选项-std=c++11
  • map 有序的,树实现,O(logn)

的确这题可能数据量不是很大用unordered_map比map快不了多少。

 

后来网上找的一个更巧妙的算法,一些方法就是要对原始结构进行修改(好像有不使用额外的栈/递/队列归遍历树),详细过程见参考[2]。

自己也写一个作为练习,最后重新分出新旧两个链表节点重新拼接的过程怎么写简洁点还是需要考虑一下。

bubuko.com,布布扣
// 2. without a map
    RandomListNode *_copyRandomList(RandomListNode *head) {
        if (head == NULL) return NULL;
        
        RandomListNode* item = new RandomListNode(head->label);
        item->random = head->random;
        item->next = head->next;
        head->next = item;
        
        RandomListNode* tail = item->next;
        
        while (tail != NULL) {
            item = new RandomListNode(tail->label);
            item->random = tail->random;
            item->next = tail->next;
            tail->next = item;
            
            tail = item->next;
        }
        tail = head;
        while (tail != NULL) {
            tail = tail->next;
            if (tail->random != NULL) tail->random = tail->random->next;
            tail = tail->next;
        }
        
        RandomListNode* newhead = head->next;
        RandomListNode* oldtail = head;
        tail = newhead;
        while (tail->next != NULL) {
            oldtail->next = tail->next;
            oldtail = tail->next;
            tail->next = oldtail->next;
            tail = oldtail->next;
        }
        oldtail->next = NULL;
        return newhead;
    }
bubuko.com,布布扣

 

速度上比原先的使用map版本快了70ms左右

参考:

[1] zhuli哥的题解 http://www.cnblogs.com/zhuli19901106/p/3518026.html

[2] 另外一篇比较详细的题解 http://www.cnblogs.com/TenosDoIt/p/3387000.html

LeetCode Copy List with Random Pointer,布布扣,bubuko.com

LeetCode Copy List with Random Pointer

原文:http://www.cnblogs.com/lailailai/p/3601292.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!