剑指offer——将复杂问题分解使其简单化
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
思路1.
- 直接先复制主链
- 之后再重复遍历,依次添加主链的随机结点,时间复杂度为O(n*n)
思路2.空间换取时间,
- 首先复制主链,之后将主链与复制链之间采用哈希表进行两条链间对应结点的配对信息;
- 之后根据哈希表直接找到复制链中每个结点的随机结点,时间复杂度为O(1)
思路3.不用辅助空间,实现O(n)时间效率
- 首先复制原始链表中每个结点N,并创建复制结点N‘,再将复制结点N’链接到结点N之后
- 复制随机结点,即如果N结点的随机结点为S,则N'的随机结点为S的后序结点S'
- 按照位置提取奇偶位置结点组成新链。
源代码如下所示(加入了是否为空操作的判断,否则会输出警告)
1 /* 2 public class RandomListNode { 3 int label; 4 RandomListNode next = null; 5 RandomListNode random = null; 6 7 RandomListNode(int label) { 8 this.label = label; 9 } 10 } 11 */ 12 /* 13 1.在旧链表中创建新的链表,此时不处理新链表的兄弟链表 14 2.根据旧链表的兄弟结点,初始化新链表中的兄弟结点 15 3.从旧链表中拆分得到新链表 16 */ 17 public class Solution { 18 public RandomListNode Clone(RandomListNode pHead) 19 { 20 if (pHead==null) 21 return null; 22 RandomListNode currentNode = pHead; 23 //复制每个结点,并将复制后的结点插入结点之后 24 while(currentNode != null){ 25 RandomListNode cloneNode = new RandomListNode(currentNode.label); 26 RandomListNode nextNode = currentNode.next; 27 currentNode.next = cloneNode; 28 cloneNode.next = nextNode; 29 currentNode = nextNode; 30 } 31 currentNode = pHead; 32 //重新遍历链表,复制老结点的随机指针给新结点 33 while(currentNode != null){ 34 currentNode.next.random = currentNode.random==null?null:currentNode.random.next; 35 currentNode = currentNode.next.next; 36 } 37 //拆分链表,将链表拆分为原链表和复制后的链表 38 currentNode = pHead; 39 RandomListNode pCloneHead = pHead.next; 40 while(currentNode!=null){ 41 RandomListNode cloneNode = currentNode.next; 42 currentNode.next = cloneNode.next; 43 cloneNode.next = cloneNode.next == null?null:cloneNode.next.next; 44 currentNode = currentNode.next; 45 } 46 return pCloneHead; 47 } 48 }