剑指offer-25.复杂链表复制(Java)

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

方法一

【解题思路】
原链表:A-B-C
1.在原结点后面复制一个结点,主要复制next域
A-B-C 变为A-A’-B-B’-C-C’

以A‘复制A为例:
当前结点p不为空,循环
新建结点m ,值域为A
结点n,存储当前p下一个结点,即B
p的下一个结点为m,即A-A’
m的下一个结点为n,即A-A’-B-C

2.复制random
假设A与C相连,复制后,A’与C’相连
当前链表为 A-A’-B-B’-C-C’

以A’复制A的random为例
p初始化为 链表第一个结点,即p = pHead
当前结点p不为空,循环
此时p为A,p.next为A’
判断p.random (A的random域)是否为空,若不为空,p.next.random(A’的random域)=p.random.next(即A的random域—C的下一个C’)
p向后移动两个结点 p=p.next.next

3.将链表拆开 A-B-C和A‘-B’-C‘

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        
        //特殊情况:链表为空
        if(pHead == null){
             return null;
        }
           
        
        //在每个结点后面复制一个结点,复制next域,原:A-B-C,现A-A'-B-B'-C-C'
        RandomListNode p = pHead; //p为当前结点        
        //以A’复制为例
        RandomListNode n = p.next;
        while(p!=null){
            RandomListNode m = new RandomListNode(p.label);//新建结点A'
            n = p.next;//将p(A)的下一个结点先保存,即保存B
            p.next = m; //A和A'相连
            m.next = n; //A'和B相连
            p = n;
        }
        
        //复制random域
        p = pHead;
        while(p!=null){           
            if(p.random!=null){
                 p.next.random = p.random.next;
            }
            else
                p.next.random = null;
           
            p = p.next.next;
                    
        }
        
        
        //将链表拆开
        p = pHead;//p初始化为pHead
        RandomListNode h = pHead.next;//复制后新链表 的头节点
        while(p!=null){
            //以A-A'-B-B'-C-C'为例,此时p为A,S为A'
            RandomListNode s = p.next;
            //A-B
            p.next = s.next;
            
            //若B不为空,A'-B'
            if(s.next!=null){
                s.next = s.next.next;
            }
            else
                s.next = null;
            //p移动为B
            p = p.next;   
        }
        
        return h;
    
    }      
}

方法二

浅谈Map map = new HashMap()
Java 中Map map = new HashMap()与HashMap map = new HashMap()区别

Map <数据类型1,数据类型2> map = new HashMap<>();
key - value 映射
放入数据 map.put(key,value);
读取value数据 map.get(key)

本题中,将原链表结点(key)与复制后的链表结点(value)进行映射

  1. 先将原链表结点与新链表结点(结点需要新建)进行映射,主要复制值,此时新链表结点只有data,next和random域为空
    map.put(cur,p)

  2. 给新链表结点 next 域和 random 域赋值
    用map.get(cur.next)

注意:判断链表为空
判断 next 和 random 是否为空

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
import java.util.*;
public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        if(pHead==null) 
            return null;
        
        Map <RandomListNode,RandomListNode> map = new HashMap<>();
        
        
        RandomListNode cur = pHead;//当前结点
        
        
        //建立原结点到复制结点之间的映射,复制值域
        while(cur!=null){
            RandomListNode p = new RandomListNode(cur.label);
            map.put(cur,p);
            cur = cur.next;                    
        }
        
        //复制next域和random域
        cur = pHead;
        while(cur!=null){
            RandomListNode s = map.get(cur);
            if(cur.next!=null)
                s.next = map.get(cur.next);
            else
                s.next = null;
            
            if(cur.random!=null){
                s.random = map.get(cur.random);
            }
            else
                s.random = null;
            
            cur = cur.next;
        }
        
        //返回新链表头节点
        cur = pHead;
        return map.get(cur);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值