zoukankan      html  css  js  c++  java
  • 剑指offer | 复杂链表的复制 | 15


    思路分析

    首先遍历两次是不行的,因为第二次遍历并不能知道第一次遍历的信息.

    其实如果是普通链表的复制是非常简单的,只需要遍历一次原来的链表,每次都新建一个节点,然后将原来节点的值复制给新节点即可.

    但是现在的问题在于有这个random指针,这个就是最大的问题.

    哈希表

    使用哈希表的方法只需要遍历两次即可.

    第一次,将值进行复制

    第二次,复制对应的nextrandom

    复杂度分析:
    时间复杂度:O(N),两轮哈希表遍历
    空间复杂度: O(N),哈希表使用线性大小的额外空间

    cpp

    /*
    // Definition for a Node.
    class Node {
    public:
        int val;
        Node* next;
        Node* random;
        
        Node(int _val) {
            val = _val;
            next = NULL;
            random = NULL;
        }
    };
    */
    class Solution {
    public:
        Node* copyRandomList(Node* head) {
            unordered_map<Node*,Node*> pos;
            pos[NULL] = NULL;
            for(auto p=head;p;p=p->next){
                pos[p] = new Node(p->val);
            }
            for(auto p=head;p;p=p->next){
                pos[p]->next = pos[p->next];
                pos[p]->random = pos[p->random];
            }
            return pos[head];
    
        }
    };
    

    python

    """
    # Definition for a Node.
    class Node:
        def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
            self.val = int(x)
            self.next = next
            self.random = random
    """
    class Solution:
        def copyRandomList(self, head: 'Node') -> 'Node':
            pos = {}
            pos[None] = None
            p = head
            while p:
                pos[p] = Node(p.val)
                p = p.next
            p = head
            while p:
                pos[p].next = pos[p.next] 
                pos[p].random = pos[p.random]
                p = p.next
            return pos[head]
    

    拼接+拆分

    这里不使用哈希表来作映射,而是使用链表拼接的方式来做映射.

    考虑构建

    原节点1->新节点1->原节点2->新节点2->原节点3->新节点3->....
    

    的拼接链表,如此便可在访问原节点的random指向节点的同时找到新对应节点的random指向节点.

    cpp

    /**
     * Definition for singly-linked list with a random pointer.
     * struct ListNode {
     *     int val;
     *     ListNode *next, *random;
     *     ListNode(int x) : val(x), next(NULL), random(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode *copyRandomList(ListNode *head) {
            for(auto p=head;p;p=p->next->next){ 
                auto q = new ListNode(p->val);
                auto ne = p->next;
                p->next = q;
                q->next = ne;
            }
            
            for(auto p=head;p;p=p->next->next)
                if(p->random)// 不然会报错
                    p->next->random = p->random->next;
            
            
            auto dummy = new ListNode(-1);
            auto cur = dummy;
            for(auto p=head;p;p=p->next){
                cur->next = p->next;
                cur = cur->next;
                p->next = p->next->next;
            }
            return dummy->next;
            
            
        }
    };
    

    python

    # Definition for singly-linked list with a random pointer.
    # class ListNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    #         self.random = None
    class Solution(object):
        def copyRandomList(self, head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            p = head
            while p:
                q = ListNode(p.val)
                ne = p.next
                p.next = q
                q.next = ne
                p = p.next.next
            
            p=head
            while p:
                if p.random:
                    p.next.random = p.random.next
                p = p.next.next
            
            dummy = ListNode(-1)
            cur = dummy
            p = head
            while p:
                cur.next = p.next
                cur = cur.next
                p.next = p.next.next
                p = p.next
            
            
            return dummy.next
    
  • 相关阅读:
    [译]为什么你要学Go?
    类Lisp解释器JavaScript实现
    前端同学Windows中生存指北
    Virtualbox
    数据发布和上线日报&周报系统开发总结
    [Lab1]五分钟了解Makefile
    解决linux下解压来自windows的zip文件产生乱码的问题
    Arch使用过程中出现的问题汇总
    jQuery为什么移除了.toggle()方法
    Linux配置DNS
  • 原文地址:https://www.cnblogs.com/Rowry/p/14305385.html
Copyright © 2011-2022 走看看