剑指offer-面试题26:复杂链表的复制
2016-04-02 20:13
549 查看
题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL。结点的C++定义如下:
struct ComplexListNode
{
int m_nValue;
ComplexListNode* m_pNext;
ComplexListNode* m_pSibling;
}
下图是一个含有5个结点的复杂链表。图中实线箭头表示m_pNext指针,虚线箭头表示m_pSibling指针。为简单起见,指向NULL的指针没有画出。
思路:书上给了三种思路。第一种简单的方法就是从链表头开始复制结点,并设置m_pNext指针。再遍历一遍设置m_pSibling指针。在原链表中需要通过遍历才能确定m_pSibling指针的相对位置,在新链表中同样需要通过m_pNext寻找每个结点的m_pSibling指针。
第二种方法通过初试步骤和第一种方法类似,复制结点和m_pNext指针,同时将原结点N和复制结点N′的配对<N, N′>放入到哈希表中。第二部还是设置复制链表上每个结点m_pSibling。有个哈希表,可以实现在O(1)时间内找到m_pSibling指针的指向结点。
第三种方法非常巧妙!直接在原链表上复制结点,复制后的结点插入被复制结点之后。最关键的设置m_pSibling指针的地方来了,假设原结点N的m_pSibling指针指向S,那么N′应该指向S′。S′很显然就是S的下一个结点,而S又可以通过N的m_pSibling指针很快的得到。最后把链表分拆就是我们要复制的链表。
总结一下第三种方法,分为三个步骤:(1)复制结点插入原结点之后;(2)设置m_pSibling指针;(3)分拆链表。
为此我们分别通过三个函数实现:
最后同时调用三个函数就可以了:
struct ComplexListNode
{
int m_nValue;
ComplexListNode* m_pNext;
ComplexListNode* m_pSibling;
}
下图是一个含有5个结点的复杂链表。图中实线箭头表示m_pNext指针,虚线箭头表示m_pSibling指针。为简单起见,指向NULL的指针没有画出。
思路:书上给了三种思路。第一种简单的方法就是从链表头开始复制结点,并设置m_pNext指针。再遍历一遍设置m_pSibling指针。在原链表中需要通过遍历才能确定m_pSibling指针的相对位置,在新链表中同样需要通过m_pNext寻找每个结点的m_pSibling指针。
第二种方法通过初试步骤和第一种方法类似,复制结点和m_pNext指针,同时将原结点N和复制结点N′的配对<N, N′>放入到哈希表中。第二部还是设置复制链表上每个结点m_pSibling。有个哈希表,可以实现在O(1)时间内找到m_pSibling指针的指向结点。
第三种方法非常巧妙!直接在原链表上复制结点,复制后的结点插入被复制结点之后。最关键的设置m_pSibling指针的地方来了,假设原结点N的m_pSibling指针指向S,那么N′应该指向S′。S′很显然就是S的下一个结点,而S又可以通过N的m_pSibling指针很快的得到。最后把链表分拆就是我们要复制的链表。
总结一下第三种方法,分为三个步骤:(1)复制结点插入原结点之后;(2)设置m_pSibling指针;(3)分拆链表。
为此我们分别通过三个函数实现:
void CloneNodes(ComplexListNode* pHead) { if(pHead == NULL) return; ComplexListNode* pNode = pHead; while(pNode != NULL) { ComplexListNode* CloneNode = new ComplexListNode[1]; CloneNode->m_nValue = pNode->m_nValue; CloneNode->m_pNext = pNode->m_pNext; CloneNode->m_pSibling = NULL; pNode->m_pNext = CloneNode; pNode = CloneNode->m_pNext; } } void ConnectSiblingNodes(ComplexListNode* pHead) { if(pHead == NULL) return; ComplexListNode* pNode = pHead; while(pNode != NULL) { ComplexListNode* pCloned = pNode->m_pNext; if(pNode->m_pSibling != NULL) { pCloned->m_pSibling = pNode->m_pSibling->m_pNext; } pNode = pCloned->m_pNext; } } ComplexListNode* ReconnectNodes(ComplexListNode* pHead) { if(pHead == NULL) return NULL; ComplexListNode* pNode = pHead; ComplexListNode* pClonedHead = NULL; ComplexListNode* pCloned = NULL; if(pNode->m_pNext != NULL) { pClonedHead = pCloned = pNode->m_pNext; pNode->m_pNext = pCloned->m_pNext; pNode = pNode->m_pNext; } while(pNode != NULL) { pCloned->m_pNext = pNode->m_pNext; pCloned = pCloned->m_pNext; pNode->m_pNext = pCloned->m_pNext; pNode = pNode->m_pNext; } return pClonedHead; }
最后同时调用三个函数就可以了:
ComplexListNode* Clone(ComplexListNode* pHead) { CloneNodes(pHead); ConnectSiblingNodes(pHead); return ReconnectNodes(pHead); }
相关文章推荐
- 一个普通程序员的中国梦
- 剑指offer面试题之判断二叉搜索树的后序序列
- ssh面试题
- 【笔试/面试】—— 序列全排列(递归版)
- 招人与面试
- 剑指offer面试题之字符串的排列
- 剑指offer-面试题25:二叉树中和为某一值的路径
- 剑指 offer代码解析——面试题39判断平衡二叉树(高效方法)
- 剑指 offer代码解析——面试题39判断平衡二叉树(高效方法)
- 10年经验的.NET老程序员推荐的7个开发类工具
- 【操作系统】:操作系统常见面试题
- 码农小汪-ReentrantLock 可重入锁
- java面试题目 5
- 【剑指Offer学习】【面试题55:字符流中第一个不反复的字符】
- 面试题思考:Stack和Heap的区别
- 码农小汪-锁 LOCK
- 程序员必知的10大基础实用性算法
- 码农小汪-synchronized
- 单链表常见面试题
- 软件应该使用中文版还是外文版