zoukankan      html  css  js  c++  java
  • LeetCode(138) Copy List with Random Pointer

    题目

    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.

    分析

    实现一个链表的深拷贝,返回拷贝后的新链表。

    若是普通链表,逐个拷贝原始链表节点并连接即可,只需O(n)的时间复杂度;但是此题特殊的是,每个节点都有一个random域可以指向该链表中的任何一个节点,所以直接复制无法处理random域,因为其指向的节点很有可能还没有创建出来。

    有两种方法处理:
    方法一:暴力解决,首先不处理random域,将原始链表复制一份,然后遍历每个原始链表节点,查找其random域,将新链表的对应节点链接,该方法需要O(n^2)的时间复杂度,给出的结果是TLE。

    方法二:充分利用原始链表的信息,不用保存原始链表的映射关系,构建新节点时,指针做如下变化,即把新节点插入到相应的旧节点后面(参考):

    例子
    同理分两步

    1、构建新节点random指针:

    new1->random = old1->random->next, new2-random = NULL, 
    new3-random = NULL, new4->random = old4->random->next

    2、恢复原始链表以及构建新链表:

    old1->next = old1->next->next,  new1->next = new1->next->next

    该算法时间复杂度O(N),空间复杂度O(1)

    AC代码

    class Solution {
    public:
        //方法一:直接复制,再修改random指针
        RandomListNode *copyRandomList1(RandomListNode *head) {
            if (!head)
                return NULL;
    
            RandomListNode *ret = new RandomListNode(head->label), *q = ret;
            RandomListNode *p = head->next;
            while (p)
            {
                RandomListNode *tmp = new RandomListNode(p->label);
                q->next = tmp;
                q = q->next;
    
                p = p->next;
            }//while
            q->next = NULL;
    
            //处理原始链表的random指针
            p = head, q = ret;
            RandomListNode *idx1 = head, *idx2 = ret;
            while (p)
            {
                if (p->random == NULL)
                    q->random = NULL;
                else{
                    idx1 = head;
                    idx2 = ret;
                    while (p->random->label != idx1->label)
                    {
                        idx1 = idx1->next;
                        idx2 = idx2->next;
                    }//while
                    q->random = idx2;
                }//else
                p = p->next;
                q = q->next;
            }//while
            return ret;
        }
    
        //方法二:充分利用原始链表信息,在每个节点后复制添加
        RandomListNode *copyRandomList(RandomListNode *head) {
            if (!head)
                return NULL;
    
            //首先,复制原始的节点,连接自身后面
            RandomListNode *p = head;
            while (p)
            {
                RandomListNode *tmp = new RandomListNode(p->label);
                //保存后续节点
                RandomListNode *r = p->next;
    
                tmp->next = r;
                p->next = tmp;
    
                p = r;
            }//while
    
            //然后,将添加的节点random 链接到原始节点random的下一个位置
            p = head;
            while (p)
            {
                RandomListNode *q = p->next;
                if (p->random == NULL)
                    q->random = NULL;
                else{
                    q->random = p->random->next;
                }//else
                //处理下一个原始节点
                p = q->next;
            }//while
    
            //最后,恢复原始链表,得到新链表
            RandomListNode *ret = head->next;
    
            p = head;
            RandomListNode *q = head->next;
            while (q->next)
            {
                p->next = q->next;
                p = q;
                if (q->next)
                    q = q->next;
            }
            p->next = NULL;
            q->next = NULL;
            return ret;
        }
    
    };

    GitHub测试程序源码

  • 相关阅读:
    Jenkins安装和初始化配置
    KVM环境下vCPU绑定到物理CPU
    关于自动化测试环境的集成(Jenkins+RobotFramework+TestLink+SVN)
    Linux下PPPoE Server测试环境搭建
    CentOS安装使用vnc进行远程桌面登录
    linux下PPTP Server测试环境搭建
    202020211 20209301《Linux内核原理与分析》第一周作业
    博弈论学习笔记(一)四个入门结论
    官宣!Amazon EMR正式支持Apache Hudi
    LessCss学习笔记 CCH
  • 原文地址:https://www.cnblogs.com/shine-yr/p/5214762.html
Copyright © 2011-2022 走看看