剑指 Offer 35. 复杂链表的复制
138. 复制带随机指针的链表
题目描述
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
输入输出
1 2
| 输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
|
基本思路
哈希解法:按照往常的链表复制,可通过构造一个前驱结点依次复制,但是本题带random指向无法确定前驱结点的random指向哪里。利用哈希表将每一个结点依次复制进入哈希表中Map<Node, Node> map = new HashMap<>();
然后构建一个新链表的引用指向即可。
时间复杂度:O(N) 两轮遍历链表
空间复杂度:O(N) 使用哈希表的额外空间
拼接拆分解法:
- 将原来的链表重组为:Node1 -> Node1New -> Node2 -> Node2New …
- 重新构建新链表的random指向
- 拆分两个链表,拆掉原来的留下新构造的并返回
时间复杂度:O(N) 三轮遍历链表
空间复杂度:O(1) 节点引用变量使用常数大小的额外空间
(Tips:如果把结果本身算上是O(N) 如果把结果视为必须使用的空间而排除在外那么就是 O(1) “原本就要新建一个链表”)
java实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
class Solution { public Node copyRandomList(Node head) { if(head == null){ return null; } Node cur = head; Map<Node, Node> map = new HashMap<>(); 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); } }
class Solution { public Node copyRandomList(Node head) { if(head == null){ return null; } Node cur = head; while(cur != null){ Node tmp = new Node(cur.val); tmp.next = cur.next; cur.next = tmp; cur = tmp.next; }
cur = head; while(cur != null){ if(cur.random != null){ cur.next.random = cur.random.next; } cur = cur.next.next; }
cur = head.next; Node pre = head, res = head.next; while(cur.next != null){ pre.next = pre.next.next; cur.next = cur.next.next; pre = pre.next; cur = cur.next; } pre.next = null; return res; } }
|