【力扣刷题笔记】复杂链表的复制 JavaScript实现

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

下面是我的错误代码示范(虽然能跑过力扣的所有测试用例,而且耗时很短,但是在数据大量重复时无法使用)

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */

// 返回random指向的copy中的node
// 严格比较
function findrandomStrict(p,pNext,copyhead){
    var copy=copyhead;
    // copy链的0号结点和1号结点不为空
    while(copy!==null&&copy.next!==null){
        // 如果copy链中0,1结点中的值等于原链对应结点的值
        if(copy.val===p.val && copy.next.val===pNext.val ){
            // 继续判断copy链中2号结点,当原链或copy链中有一个为空,说明不相等
            if((pNext.next==null&&copy.next.next!==null)||(pNext.next!==null&&copy.next.next==null)){
                copy=copy.next;
                continue;  
            }// 继续判断copy链中2号结点,若原链和copy链的2号结点值不相等,则continue
            else if(pNext.next!==null&&copy.next.next!==null){

                if(copy.next.next.val!==pNext.next.val){
                    copy=copy.next;
                    continue;  
                }      
                // 继续判断copy链中3号结点,当原链或copy链中有一个为空,说明不相等  
                else if((pNext.next.next==null&&copy.next.next.next!==null)||(pNext.next.next!==null&&copy.next.next.next==null))  {
                    copy=copy.next;
                    continue; 
                }  
                // 继续判断copy链中3号结点,若原链和copy链的3号结点值不相等,则continue
                else if(pNext.next.next!==null&&copy.next.next.next!==null&&copy.next.next.next.val!==pNext.next.next.val){
                    copy=copy.next;
                    continue;               
                }            
            }           
            return copy;
        }        
        copy=copy.next;
    }
    return null;
}
// 返回random指向的copy中的node
function findrandomEasy(p,copyhead){
    var copy=copyhead;
    while(copy!=null){
        if(copy.val==p.val){
            return copy;
        }
        copy=copy.next;
    }
    return null;
}
function findrandom(p,pNext,copyhead){    
    var copy=copyhead;
    if(p&&pNext){
        return findrandomStrict(p,pNext,copyhead);
    }
    // 如果pnext等于null,说明p指向的是链表的最后一个结点
    else if(pNext==null){
        while(copy.next!=null){
            copy=copy.next;
        }
        return copy;
    }else{
        return findrandomEasy(p,copyhead);
    }
}

/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {
    var p=head;
    if(p==null){
        return null;
    }
    // 先复制前两项
    var copy=new Node();    
    var copyHead=copy;    
    while(p!=null){
        if(p.next!=null){
            copy.next=new Node();
        }else{
             copy.next=null;
        }
        copy.val=p.val;
        
        copy.random=null;
        p=p.next;
        copy=copy.next;
    }

    // 复制random
    p=head;
    copy=copyHead;
    while(p!==null){
        if(p.random!==null){
            copy.random=findrandom(p.random,p.random.next,copyHead);
        } 
        copy=copy.next;
        p=p.next;
    }


    return copyHead;

};

然后是正确答案,原地修改链表,然后将链表拆分

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */

/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {
    if(head==null){
        return head;
    }
    // 1-2-3-4   ---->>   1-1'-2-2'-3-3'-4-4'
    var p=head;    
    while(p!=null){
        var node=new Node(p.val);
        node.next=p.next;
        p.next=node;
        p=p.next.next;
    }
    //完成链表复制节点的随机指针复制
    p=head;
    while(p!=null){
        if(p.random!=null){
            p.next.random=p.random.next;
        }
        p=p.next.next;
    }

    //将链表一分为二
    var copyhead=head.next;
    var copy=head.next;
    p=head;
    while(p!=null){
        p.next=p.next.next;
        p=p.next;
        if(copy.next!=null){
            copy.next=copy.next.next;
            copy=copy.next;
        }
    }
    return copyhead;
};
posted @   qiao101  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示