数据结构---单链表(3)
2015-07-31 10:51
274 查看
1.复杂链表的复制(剑指offer-26)
题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。其结点的C++定义如下:
java定义:
以下图为5个结点的复杂链表,实线表示m_pNext指针的指向,虚线表示m_pSibling指针的指向
方法一:
分两步
1:遍历一遍链表,用m_pNext指针将链表连起来,O(n)
2:确定每个m_pSibling指针的指向,需重新遍历新链表确定其m_pSibling的指向,O(n)
时间代价为O(n^2),空间代价为0
方法二:
针对方法1中每次确定一个结点的m_pSibling指向效率较低,利用空间换取时间,同样分两步
1:遍历一遍链表,用m_pNext指针将链表连起来的同时,将原链表中的结点N和相应复制结点N'建立哈希映射<N,N'>
2:再次遍历一遍原链表,对于每一结点m通过哈希找到m',并在原链表中找到m的m_pSibling所指向结点,再次通过哈希查找找到m'的m_pSibling指针应指向的结点,并修改m'的m_pSibling指针
时间代价为O(n),空间代价为O(n)
方法三:
比较巧妙,只需遍历3次链表,时间代价为O(n),空间代价为0,分3步
1:遍历一遍原始链表,复制结点N对应的N',将其插入到结点N的后面,如下图所示
3:再次遍历一遍,将原始链表和复制链表分开,奇数为原始链表,偶数为复制链表,得到如下图型
参考来源:
复杂链表的复制
题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。其结点的C++定义如下:
struct ComplexNode { int m_nValue; ComplexNode* m_pNext; ComplexNode* m_pSibling; };
java定义:
// 复杂链表结点(内部类) static class ComplexNode { int m_Value; // 该节点存储的值。 ComplexNode m_pNext; ComplexNode m_pSibling; ComplexNode() { this.m_pNext = null; this.m_pSibling = null; } ComplexNode(int value) { this.m_Value = value; this.m_pNext = null; this.m_pSibling = null; } }
以下图为5个结点的复杂链表,实线表示m_pNext指针的指向,虚线表示m_pSibling指针的指向
方法一:
分两步
1:遍历一遍链表,用m_pNext指针将链表连起来,O(n)
2:确定每个m_pSibling指针的指向,需重新遍历新链表确定其m_pSibling的指向,O(n)
时间代价为O(n^2),空间代价为0
方法二:
针对方法1中每次确定一个结点的m_pSibling指向效率较低,利用空间换取时间,同样分两步
1:遍历一遍链表,用m_pNext指针将链表连起来的同时,将原链表中的结点N和相应复制结点N'建立哈希映射<N,N'>
2:再次遍历一遍原链表,对于每一结点m通过哈希找到m',并在原链表中找到m的m_pSibling所指向结点,再次通过哈希查找找到m'的m_pSibling指针应指向的结点,并修改m'的m_pSibling指针
时间代价为O(n),空间代价为O(n)
方法三:
比较巧妙,只需遍历3次链表,时间代价为O(n),空间代价为0,分3步
1:遍历一遍原始链表,复制结点N对应的N',将其插入到结点N的后面,如下图所示
public static void CloneNodes(ComplexNode pHead) { ComplexNode p = pHead; while (p != null) { ComplexNode pCloned = new ComplexNode(); pCloned.m_Value = p.m_Value; pCloned.m_pNext = p.m_pNext; p.m_pNext = pCloned; pCloned.m_pSibling = null; p = pCloned.m_pNext; } }2:确定每个m_pSibling指针的指向,只需遍历一遍链表即可确定每个结点的m_pSibling指针的指向,得到如下图结构
public static void ConnectSiblingNodes(ComplexNode pHead) { ComplexNode p = pHead; ComplexNode pCloned = null; // 记录当前要确定其m_pSibling的结点 while (p != null) { pCloned = p.m_pNext; if (p.m_pSibling != null) pCloned.m_pSibling = p.m_pSibling.m_pNext; p = pCloned.m_pNext; } }
3:再次遍历一遍,将原始链表和复制链表分开,奇数为原始链表,偶数为复制链表,得到如下图型
public static ComplexNode ReconnentNodes(ComplexNode pHead) { ComplexNode pNode = pHead; ComplexNode pClonedHead = null; // 确定返回的头结点 ComplexNode pClonedNode = null; // 头结点特殊处理,边界条件判断 if (pNode != null) { pClonedHead = pNode.m_pNext; pClonedNode = pNode.m_pNext; pNode.m_pNext = pClonedHead.m_pNext; pNode = pNode.m_pNext; } while (pNode != null) { pClonedNode.m_pNext = pNode.m_pNext; pClonedNode = pClonedNode.m_pNext; pNode.m_pNext = pClonedNode.m_pNext; pNode = pNode.m_pNext; } return pClonedHead; }最终将上述3步合并,就是复制复杂链表的全过程:
public static ComplexNode Clone(ComplexNode pHead) { CloneNodes(pHead); ConnectSiblingNodes(pHead); return ReconnentNodes(pHead); }
参考来源:
复杂链表的复制
相关文章推荐
- 数据结构学习--树(一)
- 数据结构学习--树(一)
- 数据结构实验:哈希表 SDUT
- 数据结构之红黑树(三)——删除操作
- 数据结构之红黑树(三)——删除操作
- MySQL索引背后的数据结构及算法原理
- 数据结构与算法-线性表的实现(1)
- 数据结构与算法-线性表的实现(1)
- 数据结构(双向循环链表)
- 数据结构(一)---线性表
- 数据结构——图
- Linux 网卡驱动学习(三)(net_device 等数据结构)
- 华为2012机试第三题
- 数据结构---二叉树(3)
- JAVA数据结构 线性表的链式存储及其实现
- Redis源代码-数据结构Adlist双端列表
- 数据结构复习之用两个栈模拟队列操作
- 【数据结构】红黑树
- 数据结构基本概念
- 数据结构 并查集 路径压缩