• LeetCode Copy List with Random Pointer


    /**
     * 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;
        }
    };

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

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

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

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

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

    // 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;
        }

     速度上比原先的使用map版本快了70ms左右(从提交的结果来看)

    参考:

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

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

  • 相关阅读:
    k8s中service 的iptables
    xbak 备份
    tcp/ip 拥塞控制、重传、丢包、优化
    mysql 主从详细原理 以及prom 监控的对象
    内核参数优化limit.conf与sysctl.conf
    k8s 中(生产|测试)环境隔离问题
    mysql锁以及配置优化
    mysql5.6迁移mysql5.7(生产中、短中断)
    mysql 日志方面与备份、恢复
    Apollo&&Eureka安装配置
  • 原文地址:https://www.cnblogs.com/lailailai/p/3601292.html
Copyright © 2020-2023  润新知