《剑指offer》刷题——【分解让复杂问题简单化】面试题35:复杂链表的复制(java实现)

《剑指offer》刷题——【分解让复杂问题简单化】面试题35:复杂链表的复制(java实现)

一、题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针
指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中
的节点引用,否则判题程序会直接返回空)

二、题目分析

在这里插入图片描述
在复杂链表的节点中,除了有指向下一个节点的指针(实线箭头),还有指向任意节点的指针(虚线箭头)

方法一:普通方法 O(n^2)

  • (1)复制原始链表上的每一个节点,并用m_pNext链接起来
  • (2)设置每个节点的 m_pSibling指针(每一个需要从链表头开始经过O(n)步才能找到)

方法二、借助辅助空间的O(n)解法

  • (1)复制原始链表上的每一个节点N创建N,并用m_pNext链接起来;并将<N, N`> 的配对信息放到一个哈希表中
  • (2)设置复制链表上每一个m_pSibling(==由于有了哈希表,可以用O(1)的时间根据s找到s`)

方法三、不借助辅助空间的O(n)解法

  • 根据原始链表的每个节点创建对应的N^(把N ^ 链接在N的后面)
    在这里插入图片描述
  • 设置复制出来的节点的m_pSibling(把N^ 的m_pSibling指向N的m_pSibling)
    在这里插入图片描述
  • 把长链表拆分成两个链表:奇数位置的节点用pNext链接起来就是原始链表,偶数位置则是复制链表
    在这里插入图片描述

三、代码实现

/*
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)
    {
        //复制原始链表
        CloneNodes(pHead);
        //设置随机链接
        ConnectSiblingNodes(pHead);
        //拆分链表
        return ReconnectNodes(pHead);
    }
    
    /**
    * 1.复制原始链表的任意节点N并创建新节点N`,再把N`链接到N的后面
    */
    public void CloneNodes(RandomListNode pHead){
        RandomListNode node = pHead;//链表指针
        //遍历原始链表
        while(node != null){
            //新建一个节点
            RandomListNode cloned = new RandomListNode(node.label);
            //复制节点
            //cloned.label = node.label;
            cloned.next = node.next;
            cloned.random = null;
            
            //并将复制节点链接在原始节点之后
            node.next = cloned;
            //更改下一个遍历到的节点,为复制节点的下一节点
            node = cloned.next;         
        }
    }
    
    /**
    * 2. 设置复制出来的节点的random
    */
    public void ConnectSiblingNodes(RandomListNode pHead){
        //遍历
        RandomListNode node = pHead;
        while(node != null){
            RandomListNode cloned = node.next;
            //若遍历到的节点有random指向
            if(node.random != null){
                //则复制节点的random即为原始节点的random的下一节点
                cloned.random = node.random.next;
            }
            //更改下一个遍历到的节点,为复制节点的下一节点
            node = cloned.next;
        }
    }
    
    /**
    * 3. 把长表拆分成两个链表,奇数位为原始链表,偶数位为复制链表
    */
    public RandomListNode ReconnectNodes(RandomListNode pHead){
        RandomListNode node = pHead;//原始链表指针
        RandomListNode clonedHead = null; //复制链表头指针
        RandomListNode clonedNode = null; //复制链表指针
        
        //若链表不为空
        if(node != null){
            clonedHead = clonedNode = node.next;//初始化复制链表头指针 指针
            node.next = clonedNode.next;//将奇数节点的下一节点指向偶数节点的下一节点
            node = node.next; //遍历指针后移
        }
        
        //循环拆分奇偶位
        while(node != null){
            //复制链接
            clonedNode.next = node.next;
            clonedNode = clonedNode.next;
            //原始链表连接
            node.next = clonedNode.next;
            //遍历节点后移
            node = node.next;
        }
        //返回复制链表的头指针
        return clonedHead  
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值