剑指 Offer 35. 复杂链表的复制

题目链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof

本文解法采取两种两种编程语言: 一、JavaScript (1.暴力解法  2.递归【较优】)  二、Java(暴力解法)

一、JavaScript

1.暴力解法

 1 /**
 2  * @param {Node} head
 3  * @return {Node}
 4  */
 5 var copyRandomList = function (head) {
 6   if (head == null) return head;
 7   let newHead = new Node(head.val, null, null);
 8   // 第一步,根据next复制链表以及其val、next;
 9   let tem1 = head.next;
10   let tem2 = newHead;
11   while (tem1 !== null) {
12     let tem3 = new Node(tem1.val, null, null);
13     tem2.next = tem3;
14     tem2 = tem2.next;
15     tem1 = tem1.next;
16   }
17   // 第二步,复制链表的random
18   let tem4 = newHead;
19   let tem5 = head;
20   // 遍历链表,复制每个结点的random
21   while (tem5 !== null) {
22     if (tem5.random === null) {
23       // 若当前结点的random
24       tem4.random = null;
25     } else {
26       let tem6 = head;
27       let tem7 = newHead;
28       // 将当前结点的random值与链表中的结点逐个比较
29       while (tem6 !== null) {
30         if (tem5.random === tem6) {
31           tem4.random = tem7;
32         }
33         tem6 = tem6.next;
34         tem7 = tem7.next;
35       }
36     }
37     tem4 = tem4.next;
38     tem5 = tem5.next;
39   }
40   return newHead;
41 };

2.递归(一)

/**
 * @param {Node} head
 * @return {Node}
 */
 var copyRandomList = function(head, map = new Map()) {
    if(head === null) return null;
    let newHead = null;
    // 通过map存储已经遇到过的节点,用原节点(引用)作为key,复制出的节点作为value存储。
    if(map.has(head)) {
      newHead = map.get(head);
    } else {
      newHead = new Node(head.val);
      map.set(head, newHead);
    }
    // 判断当前遍历的的节点是否有random节点
    if(head.random != null) {
      let random = head.random;
      if(map.has(random)) {
        newHead.random = map.get(random);
      }else {
        newHead.random = new Node(random.val);
        map.set(random, newHead.random);
      }
    }
    // 完成子链的复制,返回链头
    newHead.next = copyRandomList(head.next, map);
    return newHead;
};

 

2.递归 (二)

 1 /**
 2  * copyRandomList(head,cachedNode): 创建该head结点(包括其val、next、random)
 3  * cachedNode:相当于一个不重复的结点池,被创建的结点保存于此。
 4  * 
 5  * 从当前结点开始,向next、random两个方向探索结点,
 6  * 所遇到的结点若未创建,则对其进行创建
 7  */
 8 var copyRandomList = function (head, cachedNode = new Map()) {
 9   if (head === null) return null;
10   if (!cachedNode.has(head)) {
11     /**
12      * 若当前结点是首次被探索到的则对其进行复制(分两步):
13      * 1、复制val
14      * 2、复制next、random 
15      */
16     cachedNode.set(head, { val: head.val });
17     Object.assign(
18       cachedNode.get(head),
19       { next: copyRandomList(head.next, cachedNode), random: copyRandomList(head.random, cachedNode) }
20     )
21   }
22   return cachedNode.get(head); 
23 }

 

二、Java

 1 class Node {
 2     int val;
 3     Node next;
 4     Node random;
 5 
 6     public Node(int val) {
 7         this.val = val;
 8         this.next = null;
 9         this.random = null;
10     }
11 }
12 
13 /**
14  * @author 不乏理想的三师弟
15  * 解法一
16  */
17 public Node copyRandomList(Node head) {
18     if(head == null) return null;
19     // 第一步:忽略random,复制一条链。
20     Node myHead = new Node(head.val);
21     Node tem = null;
22     Node tem2 = null;
23     if(head.next != null) {
24         tem = new Node(head.next.val);
25         myHead.next = tem;
26         tem2 = head.next.next;
27     }
28     while(tem2 != null) {
29         tem.next = new Node(tem2.val);
30         tem = tem.next;
31         tem2 = tem2.next;
32     }
33     /**
34      * 第二步:遍历链表,依次找出结点的random并复制
35      * 难点:确认random所指向结点的相对位置
36      * (题目要求:不只是要求值的相同,而且结点的相对位置也得相同)
37      * 手段:通过对比random所指结点的next是哪一个结点就知道其相对位置了
38      */
39     Node temMyHead = myHead;
40     Node temHead = head;
41     Node tem3;
42     
43     while(temHead != null) {
44         if(temHead.random == null) {
45             temMyHead.random = null;
46         }else {
47             // 保存当前结点random所指结点的next结点
48             tem = temHead.random.next; // tem变量的重复利用
49             // 再次遍历链表
50             tem2 = head;    // tem2变量的重复利用
51             tem3 = myHead;
52             while(tem2 != null) {
53                 if(tem2.next == tem) {
54                     temMyHead.random = tem3;
55                     break;
56                 }
57                 tem2 = tem2.next;
58                 tem3 = tem3.next;
59             }
60         }
61         temHead = temHead.next;
62         temMyHead = temMyHead.next;
63     }
64     return myHead;
65 }

 

posted @ 2021-08-13 23:46  不乏理想的三师弟  阅读(47)  评论(0)    收藏  举报