面试题30:复杂链表的复制
2015-12-25 15:44
639 查看
题目:请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复制链表中,每一个结点除了有一个m_pNext指针指向下一个结点处,还有一个m_pSibling指向链表中的任意结点或者NULL。
结点定义如下:
思路:
首先要明白复制链表的意思,是重新new相同数量的结点,然后将这些结点按原来链表的的链接方式连起来。
如果没有那个任意指针,则可以按顺序复制链表就行了。
当然可以先复制Next指针,时间复杂度O(n),再复制pSibling指针,由于要查找,重新定位,时间复杂度O(n^2)。
当然也可以先复制Next指针,然后将原结点指针和新节点指针用map对应起来,这样用O(n)的空间换来O(1)的查找时间,最后的总时间复杂度为O(n)。
下面提供一种O(n)时间复杂度,O(1)空间复杂度的思路(参考剑指offer):
第一步:将复制的结点接在原结点的后面。
第二步:复制pSibling。
第三步:将链表分成两个链表。
下面补上利用hash table思想的代码:
结点定义如下:
struct ComplexListNode{ int m_nValue; ComplexListNode* m_pNext; ComplexListNode* m_pSibling; };
思路:
首先要明白复制链表的意思,是重新new相同数量的结点,然后将这些结点按原来链表的的链接方式连起来。
如果没有那个任意指针,则可以按顺序复制链表就行了。
当然可以先复制Next指针,时间复杂度O(n),再复制pSibling指针,由于要查找,重新定位,时间复杂度O(n^2)。
当然也可以先复制Next指针,然后将原结点指针和新节点指针用map对应起来,这样用O(n)的空间换来O(1)的查找时间,最后的总时间复杂度为O(n)。
下面提供一种O(n)时间复杂度,O(1)空间复杂度的思路(参考剑指offer):
第一步:将复制的结点接在原结点的后面。
第二步:复制pSibling。
第三步:将链表分成两个链表。
#include <iostream> #include <vector> #include <queue> #include <string> #include <stack> #include <algorithm> using namespace std; struct ComplexListNode{ char m_nValue; ComplexListNode* m_pNext; ComplexListNode* m_pSibling; ComplexListNode(char val) :m_nValue(val), m_pNext(NULL), m_pSibling(NULL){} }; /*将链表的每一个结点复制,且接在原来结点的后面*/ void copyNode(ComplexListNode* head) { while (head) { ComplexListNode* cNode = new ComplexListNode(head->m_nValue+'A'-'a'); cNode->m_pNext = head->m_pNext; head->m_pNext = cNode; head = cNode->m_pNext; } } /*复制pSibling,新结点的pSibling是前一个结点pSibling所指结点的下一个结点*/ void copySibNode(ComplexListNode* head) { while (head) { ComplexListNode* hNextNode=head->m_pNext; hNextNode->m_pSibling = head->m_pSibling->m_pNext; //key head = head->m_pNext->m_pNext; } } /*将链表分成两个链表,返回新链表的头结点*/ ComplexListNode* dividList(ComplexListNode* head) { if (!head) return NULL; ComplexListNode* newHead = head->m_pNext; while (head) { ComplexListNode* temp= head->m_pNext; head->m_pNext = temp->m_pNext; head = head->m_pNext; if (head) temp->m_pNext = head->m_pNext; else temp->m_pNext = NULL; } return newHead; } ComplexListNode* Clone(ComplexListNode* pHead) { copyNode(pHead); copySibNode(pHead); return dividList(pHead); } void display(ComplexListNode* a) { while (a) { cout << a->m_nValue << "--->"<<a->m_pSibling->m_nValue<<endl; a = a->m_pNext; } } int main() { ComplexListNode* a = new ComplexListNode('a'); ComplexListNode* b = new ComplexListNode('b'); ComplexListNode* c = new ComplexListNode('c'); ComplexListNode* d = new ComplexListNode('d'); a->m_pNext = b; b->m_pNext = c; c->m_pNext = d; a->m_pSibling = c; b->m_pSibling = d; c->m_pSibling = b; d->m_pSibling = a; ComplexListNode* newHead = Clone(a); display(newHead); return 0; }
下面补上利用hash table思想的代码:
#include <iostream> #include <vector> #include <queue> #include <string> #include <stack> #include <algorithm> #include <map> using namespace std; struct ComplexListNode{ char m_nValue; ComplexListNode* m_pNext; ComplexListNode* m_pSibling; ComplexListNode(char val) :m_nValue(val), m_pNext(NULL), m_pSibling(NULL){} }; ComplexListNode* copyNode(ComplexListNode* pHead, map<ComplexListNode*, ComplexListNode*> &hash) { if (!pHead) return NULL; ComplexListNode* newHead = NULL; ComplexListNode* pre = NULL; while (pHead) { ComplexListNode* temp = new ComplexListNode(pHead->m_nValue + 'A' - 'a'); if (!newHead) newHead = temp; else pre->m_pNext = temp; hash.insert(make_pair(pHead, temp)); pHead = pHead->m_pNext; pre = temp; } return newHead; } void copySibNode(ComplexListNode* pHead, ComplexListNode* nHead, map<ComplexListNode*, ComplexListNode*> &hash) { while (pHead) { nHead->m_pSibling = hash[pHead->m_pSibling]; pHead = pHead->m_pNext; nHead = nHead->m_pNext; } } ComplexListNode* Clone(ComplexListNode* pHead) { map<ComplexListNode*, ComplexListNode*> hash; ComplexListNode* newHead = copyNode(pHead, hash); copySibNode(pHead, newHead, hash); return newHead; } void display(ComplexListNode* a) { while (a) { cout << a->m_nValue << "--->"<< a->m_pSibling->m_nValue << endl; a = a->m_pNext; } } int main() { ComplexListNode* a = new ComplexListNode('a'); ComplexListNode* b = new ComplexListNode('b'); ComplexListNode* c = new ComplexListNode('c'); ComplexListNode* d = new ComplexListNode('d'); a->m_pNext = b; b->m_pNext = c; c->m_pNext = d; a->m_pSibling = c; b->m_pSibling = d; c->m_pSibling = b; d->m_pSibling = a; ComplexListNode* newHead = Clone(a); display(newHead); return 0; }
相关文章推荐
- 如何提升程序员的工作效率?
- 前端工程师应该注意的一些细节,面试容易问到
- 技术人员如何去面试?
- 程序员该做的事
- 最全iOS面试题
- 程序员最好的时代来了(4)
- Java程序员之JS(一) 入门
- 程序员最好的时代来了(3)
- 一道JS前端闭包面试题解析
- C面试基础题-全局变量,静态变量,局部变量(1)
- 程序员的爱情诗
- 程序员的爱情诗
- iOS面试题6
- 面试总结
- 68个面试技巧(任何职业均适用)
- MBTI职业性格测试
- 一个神的职业生涯么么哒:在此讲述一个人的成神之路,不定时更新。哈哈哈
- 黑马程序员--OC--封装、继承、多态
- Java线程面试题 Top 50
- 【剑指offer】2.3.5栈和队列——面试题7:用两个栈实现队列