MENU

LeetCode138. 复制带随机指针的链表

August 8, 2018 • Read: 3279 • LeetCode阅读设置

题目链接:LeetCode138展开目录

题解展开目录

第一步:复制结点,复制的结点放在待复制的结点后,依然组成一个单链表
第二步:串接随机指针
第三步:将原单链表与复制链表拆开

代码展开目录
  • class Solution {
  • public RandomListNode copyRandomList(RandomListNode head) {
  • if (head == null) {
  • return null;
  • }
  • copyNode(head);
  • linkRandomPointer(head);
  • return splitList(head);
  • }
  • /**
  • * 复制结点,复制的结点放在待复制的结点后,依然组成一个单链表
  • *
  • * @param head 链表头
  • */
  • public void copyNode(RandomListNode head) {
  • // 记录当前要被复制的缜
  • RandomListNode node = head;
  • while (node != null) {
  • // 复制一个新的结点
  • RandomListNode copyNode = new RandomListNode(node.label);
  • // 将结点串接到被复制的结点后,并且依然组成单链表
  • copyNode.next = node.next;
  • node.next = copyNode;
  • node = copyNode.next;
  • }
  • }
  • /**
  • * 串接随机指针
  • *
  • * @param head 链表头
  • */
  • public void linkRandomPointer(RandomListNode head) {
  • // 记录当前要被复制的缜
  • RandomListNode node = head;
  • while (node != null) {
  • // 随机指针有指向某个具体的结点
  • if (node.random != null) {
  • // 串接node被复制结点的随机指针
  • node.next.random = node.random.next;
  • }
  • // 指向下一个被复制的结点
  • node = node.next.next;
  • }
  • }
  • /**
  • * 将链表拆分,还原原来的链表,并且组装拷贝的链表
  • *
  • * @param head 链表头
  • * @return 拷贝的新链表头
  • */
  • public RandomListNode splitList(RandomListNode head) {
  • // 新链表头
  • RandomListNode copyHead = head.next;
  • // 当前处理的被复制的结点
  • RandomListNode node = head;
  • // 当前复制的结点
  • RandomListNode copy;
  • while (node != null){
  • // 指向复制结点
  • copy = node.next;
  • // node.next指向下一个被复制的结点
  • node.next = copy.next;
  • // 下一个被复制的结点不为null
  • if (node.next != null) {
  • // copy.next指向下一个复制的结点
  • copy.next = node.next.next;
  • }
  • // node指向下一个要被处理的被复制结点
  • node = node.next;
  • }
  • return copyHead;
  • }
  • }
另一种做法展开目录

利用哈希表,HashMap 的 key 是 Node 类型,value 也是 Node 类型,首先遍历一遍链表,将经过的所有结点都拷贝一份相同值的新结点,这一对结点存到哈希表中

然后再重新遍历结点,此时遍历结点的目的就是为了构建 next 指针和 random 指针。具体做法就是,将拷贝的结点的 next 指针设为 key 的 next 指针指向的结点,也就是 map.get(cur).next=map.get(cur.next)。同样的,将拷贝节点的 random 指针设为 key 的 random 指针指向的结点,也就是 map.get(cur).random=map.get(cur.random)

代码展开目录
  • /**
  • * Definition for singly-linked list with a random pointer.
  • * class RandomListNode {
  • * int label;
  • * RandomListNode next, random;
  • * RandomListNode(int x) { this.label = x; }
  • * }
  • */
  • public class Solution {
  • public RandomListNode copyRandomList(RandomListNode head) {
  • HashMap<RandomListNode,RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
  • RandomListNode cur = head;
  • while(cur != null) {
  • map.put(cur,new RandomListNode(cur.label));
  • 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);
  • }
  • }
Last Modified: May 12, 2021
Archives Tip
QR Code for this page
Tipping QR Code