剑指Offer 35 - 复杂链表的复制
Posted xintangchn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer 35 - 复杂链表的复制相关的知识,希望对你有一定的参考价值。
力扣链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/
题目描述
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
思路
很容易想到的步骤是首先复制简单链表,忽略random,然后再遍历一次链表复制random。但由于链表不支持随机存取,且Node是引用类型,如何在新链表中定位random就成为问题的关键。(例如在原链表中,head.random为第10个节点,我们就需要遍历完新链表的前十个节点,才能定位到newHead.random, 并且由于Node是引用类型,判断newHead.random和head.random一样也比较复杂)
有两种方法解决:
- 法一:用哈希表存储原节点到复制节点的映射关系
- 法二:复制所有节点,使得复制节点位于原始节点的下一个,形成位置上的映射关系
法一:
/** * // Definition for a Node. * function Node(val, next, random) { * this.val = val; * this.next = next; * this.random = random; * }; */ /** * @param {Node} head * @return {Node} */ var copyRandomList = function(head) { if(!head) return null; const copyHead = new Node(head.val, null, null); //1. 复制节点,保存map let copyCur = copyHead; let cur = head; const map = new Map(); while(cur){ map.set(cur, copyCur); let copyNext = cur.next ? new Node(cur.next.val, null, null) : null; copyCur.next = copyNext; copyCur = copyCur.next; cur = cur.next; } //2.处理random cur = head; copyCur = copyHead; while(cur){ if(cur.random){ copyCur.random = map.get(cur.random); } cur = cur.next; copyCur = copyCur.next; } return copyHead; };
易错:凡涉及node.next.val一定要考虑node.next为null的情况。
时间复杂度:O(N)
空间复杂度:O(N)
法二:
- 复制所有节点,新节点的random统一指向null。1->2->3->null 改为 1->1->2->2->3->3->null
- 处理新节点的random指针,指向原节点的random 的复制节点(即next节点)
- 分离原链表和复制链表,依次修改next指针
代码:
/** * // Definition for a Node. * function Node(val, next, random) { * this.val = val; * this.next = next; * this.random = random; * }; */ /** * @param {Node} head * @return {Node} */ var copyRandomList = function(head) { if(!head) return null; let original = head; //1. 复制节点 while(original){ let originalNext = original.next; let copy = new Node(original.val, originalNext, null); original.next = copy; original = original.next.next; } //2.处理random original = head; while(original){ if(original.random){ original.next.random = original.random.next; } original = original.next.next; } //3.分离链表 original = head; let copyHead = head.next; while(original){ let copy = original.next; original.next = copy.next; if(original.next){ copy.next = original.next.next; } original = original.next; } return copyHead; };
易错:同上,涉及.next.random / .next.val 一定注意判断对象是否可能为空。
时间复杂度:O(N)
空间复杂度:O(1)
以上是关于剑指Offer 35 - 复杂链表的复制的主要内容,如果未能解决你的问题,请参考以下文章