剑指offer--面试题26:复杂链表的复制--Java实现
2015-06-23 20:14
711 查看
题目描述:
复制一个复杂链表,在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sbiling指向链表中的任意结点或者null。下图是一个复杂链表的示例,Null的指针没有画出。
解题思路:
1.很直观的解法就是分成两步:
1).复制原始链表上的每一个结点,并用next指针连起来。2).复制sbiling指针。
但是复制sbiling指针时需要比较高的复杂度。
以上图为例,如果我们要复制B对应B’的的sbiling指针,那就是要找到E’,想要找到E’只能根据
B到E要走的步数 = B’到E’要走的步数
然而又如D.sbiling = B,指向的结点在它的前面,而链表并没有指向前一个元素的指针,所以,每次都只能根据从链表头结点到目标的结点的步数来找到sbiling应该指向的元素。
这种方法显然效率太低,时间复杂度达到了O(n*n)。
2.书中提到了利用哈希表存储(N, N’)的配对信息的方法
这是一个在时间上很高效的方法,在查找上,利用哈希表的高效性。但是缺点在于要用额外的空间。3.更为高效的一种不利用辅助空间的方法
这个方法的巧妙之处在于利用链表结点本身记录sbiling指针的位置。分成三个步骤
1).根据原始链表的每个结点N创建对应的N’,并把N’连在N的后面。
如下图:
2)看到上图我们就应该知道这个算法的巧妙之处了,B’.sbiling就记录在B.sbiling.next,这一步就是通过这个方法设置sbiling指针了。
3).将两个链表断开。
代码如下:
public class CopyComplexListTest { static class Node{ int value; Node next; Node sbiling; @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("value = " + value); sb.append(", next = " + (next == null ? "null" : next.value)); sb.append(", sbiling = " + (sbiling == null ? "null" : sbiling.value)); return sb.toString(); } } public static void copyList(Node head){ Node node = head; while(node != null){ Node copyNode = new Node(); copyNode.value = node.value; copyNode.next = node.next; copyNode.sbiling = null; node.next = copyNode; node = copyNode.next; } } public static void setSbiling(Node head){ Node node = head; while(node != null){ Node copyNode = node.next; if(node.sbiling != null){ copyNode.sbiling = node.sbiling.next; } node = copyNode.next; } } public static Node disConnectList(Node head){ Node node = head; Node copyHead = null; Node copyNode = null; if(node != null){ copyHead = node.next; copyNode = node.next; node.next = copyNode.next; node = node.next; } while(node != null){ copyNode.next = node.next; copyNode = copyNode.next; node.next = copyNode.next; node = node.next; } return copyHead; } public static Node copy(Node head){ copyList(head); setSbiling(head); return disConnectList(head); } public static void main(String[] args) { Node head = new Node(); head.value = 1; Node node2 = new Node(); node2.value = 2; Node node3 = new Node(); node3.value = 3; Node node4 = new Node(); node4.value = 4; Node node5 = new Node(); node5.value = 5; head.next = node2; head.sbiling = node3; node2.next = node3; node2.sbiling = node5; node3.next = node4; node4.next = node5; node4.sbiling = node2; Node copyHead = copy(head); Node node = copyHead; while(node != null){ System.out.println(node); node = node.next; } } }
相关文章推荐
- 面试常见算法-排序查找算法
- 黑马程序员_关于本人对面向对象的一点小看法
- 黑马程序员--刚学完集合,也看了一些资料,做个总结,
- 几个面试经典算法题Java解答
- 黑马程序员_JAVA的异常处理_2_总结
- 黑马程序员——java高新技术——反射
- LR经典面试题
- 黑马程序员--OC--分类和重新定义description方法
- 黑马程序员--set和get方法
- 面试总结2
- 黑马程序员--面向对象的语法
- 为Java程序员编写的Scala的入门教程
- 黑马程序员——Java基础:多线程
- 黑马程序员--Java学习日记之总结复习(多线程和设计模式)
- 黑马程序员--Java学习日记之复习总结(递归以及IO流概述)
- 黑马程序员--Java学习日记之常见类的功能概述(多练习)
- 程序员薪资福利指南
- 黑马程序员——Java常用类笔记(下)【Math类、Random类、System类、Date类】
- 比较基础常用的java面试题(4)
- 黑马程序员——Java面向对象之抽象类 接口 内部类笔记