• [LeetCode] 138. Copy List with Random Pointer


    1. 原题链接:https://leetcode.com/problems/copy-list-with-random-pointer/

    2. 解题思路

    2.1 映射表
    1. 建立新旧节点之间的映射表:old->new,来解决复制random指针
    2.2 克隆链表
    1. 创建一个包含新节点的克隆链表:A --> A' --> B --> B' --> C --> C' --> D --> D'
    2. 关键点:A'的random指针等于A的random指针指向的节点的next节点

    3. 算法

    3.1 映射表
    1. 建立新旧节点之间的映射表:old->new
    2. 遍历链表两次:
      1. 第一次遍历:构造新链表,只是对新链表的next指针进行赋值,同时建立旧节点和新建节点之间的映射表,此时不对random指针进行赋值
      2. 第二次遍历:根据映射表的映射关系,对新链表的random指针进行赋值
    3.2 克隆链表
    1. 第一步:遍历原始链表:A --> B --> C --> D,创建一个包含新节点的克隆链表:A --> A' --> B --> B' --> C --> C' --> D --> D',注意此时不对random指针进行赋值
    2. 第二步:遍历新链表,当遍历到原始链表节点时,对该节点的下一个节点(也就是A和A'的关系)的random指针进行赋值,该random指针指向原始节点的random指针指向的下一个节点
    3. 第三步:遍历新链表,把新节点从新链表中挑选出来,构成最终的copy链表并返回

    4. 实现

    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) {
            //建立新旧节点之间的映射表:old->new
            map<Node*, Node*> table;
            //第一次遍历:构造新链表,此时不对random指针进行赋值
            Node dummy(-1);
            Node *cur = head;
            Node *new_cur = &dummy;
            for(; cur != NULL; cur = cur->next, new_cur = new_cur->next){
                int v = cur->val;
                Node *new_node = new Node(v);
                table[cur] = new_node; //关键点:建立旧节点指针到新节点指针的映射
                new_cur->next = new_node;
            }
            
            //第二次遍历:对新链表的random指针进行赋值
            cur = head;
            new_cur = dummy.next;
            for(; cur != NULL; cur = cur->next, new_cur = new_cur->next){
                Node *r = cur->random;
                Node *new_r = table[r];
                new_cur->random = new_r;
            }
            return dummy.next;
        }
    };
    
    克隆链表
    class Solution {
    public:
        Node* copyRandomList(Node* head) {
            if(!head)   return head;
            //copy new node and changing new node next pointer to old node next pointer and  old node next pointer to new node
            Node *newHead = NULL, *l1, *l2;
            for(l1 = head; l1 != NULL; l1 = l1->next->next){
                l2 = new Node(l1->val, l1->next, NULL);
                l1->next = l2;
            }
            newHead = head->next;
            //fixing the random pointer of the cloned list
            for(l1= head; l1 != NULL; l1 = l1->next->next){
                if(l1->random) l1->next->random = l1->random->next;
            }
            //changing the next node of both old and new list
            for(l1 = head; l1 != NULL; l1 = l1->next){
                l2 = l1->next;
                l1->next = l2->next;
                if(l2->next)l2->next = l2->next->next;
            }
            return newHead;
        }
    };
    
  • 相关阅读:
    iOS微信支付
    iOS登录及token的业务逻辑(没怎么用过,看各种文章总结)
    IOS 支付宝支付开发流程
    iOS SDWebImage实现原理
    站立会议1
    作业六:团队项目——编写项目的Spec
    作业5
    站立会议8
    站立会议 3
    站立会议 2
  • 原文地址:https://www.cnblogs.com/wengle520/p/12330664.html
Copyright © 2020-2023  润新知