10、复制含有随机指针节点的链表(JAVA)--链表

112 阅读2分钟

题目描述:

image.png 题目链接:leetcode.cn/problems/fu…

注意:本题中的复制指的是深拷贝,也就是要返回一个全新的链表,且最终原链表的状态不能改变。


思路解析:

方法一:哈希表(HashMap)

遍历一遍原链表,以原链表中的老节点为Key,以老节点的深拷贝为value,以此存入map中,如图:

image.png

再遍历一遍原链表,将每个新节点原链表中对应的老节点的next、random的顺序连接,最后组成一个新链表,返回新链表的头节点即可,如图所示:

image.png


方法二:插入法(不使用额外API)

将每个复制节点插入对应的老节点的后面,如图所示:

image.png 然后按原链表中老节点的next、random的连接顺序将复制节点依次连接成新链表即可。注意保持原链表的状态不变。(连好的图有些复杂,这里就不作图示了)


伪代码:

方法一:哈希表(HashMap)

package 苟熊岭熊哒;

import java.util.HashMap;
class Solution {
    public Node copyRandomList(Node head) {
      if(head==null){
        return null;
      }

      HashMap<Node,Node> map=new HashMap<>();
      //哈希表,Key存老结点,Value存新结点
      Node cur=head;//复杂头结点
      
      //遍历一遍老链表,存值
      while(cur!=null){
        map.put(cur,new Node(cur.val));
        //存入新结点
        cur=cur.next;
      }

      //再遍历一遍老链表,连接新链表中的结点
      cur=head;
      while(cur!=null){
        map.get(cur).next=map.get(cur.next);
        map.get(cur).random=map.get(cur.random);
        //用老结点来找新结点
        cur=cur.next;
      }

      return map.get(head);
    }
}

测试结果:

image.png


方法二:插入法(不使用额外API)

package 苟熊岭熊哒;

class Solution {
    public Node copyRandomList(Node head) {
        if(head==null){
          return null;//链表为空时,直接返回空指针
        }

        Node cur=head;//复制原链表头节点的位置
        Node Next=null;

        //第一遍遍历--将每个新结点放到对应旧结点的后面
        while(cur!=null){
          Next=cur.next;
          cur.next=new Node(cur.val);//创建新节点
          cur.next.next=Next;
          cur=Next;
        }

        //第二遍遍历--设置每个新结点的random
        cur=head;
        Node curCopy=null;//表示新链表的节点(旧节点的复制)
        while(cur!=null){
          Next=cur.next.next;//表示旧节点的位置
          curCopy=cur.next;//表示旧节点的复制
          //↓注意原链表的random可能为空指针
          curCopy.random=cur.random==null?null:cur.random.next;
          cur=Next;
        }

        //第三遍遍历--将每个新结点连成一条完整的新链表
        cur=head;
        Node newHead=head.next;//新链表的头节点
        while(cur!=null){
          Next=cur.next.next;//表示旧节点的位置
          curCopy=cur.next;//表示旧节点的复制
          cur.next=Next;//保持原链表的连接状态不变
          curCopy.next=Next==null?null:Next.next;//Next为空时,表示Next此时为尾节点
          cur=Next;
        }

        return newHead;//返回新链表的头节点
    }
}

测试结果:

image.png


这道题的介绍到这里就结束了,如果你觉得本篇文章对你多少有些帮助,可以点个赞或者收藏一波支持支持,欢迎各位大佬批评指正,咱们下次再见!