复杂链表的复制
Posted tianzeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复杂链表的复制相关的知识,希望对你有一定的参考价值。
题目
请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表,在复杂链表中,每个结点除了有一个pNext指针指向下一个结点之外,还有一个pSibling指向链表中的任意结点或者NULL。
思路
方法一
复制原始链表上的每一个结点,并通过pNext连接起来;然后再设置每个结点的pSibling指针。
假设原始链表中某个结点N的pSibling指针指向结点S,那么就需要从头到尾遍历查找结点S,如果从原始链表的头指针开始,经过m步之后达到结点S,那么在复制链表中的结点N‘的pSibling指针指向的结点也是距离复制链表s步的结点。通过这种办法就可以为复制链表上的每个结点设置pSibling指针。
时间复杂度:O(N^2)
方法二
方法1是通过链表查找来得到pSibling指针所指向的结点,实际上我们可以通过空间换取时间,将原始链表和复制链表的结点通过哈希表对应起来,这样查找的时间就从O(N)变为O(1)。具体如下:
复制原始链表上的每个结点N创建N‘,然后把这些创建出来的结点用pNext连接起来。同时把<N,N‘>的配对信息方法一个哈希表中;然后设置复制链表中的每个结点的pSibling指针,如果原始链表中结点N的pSibling指向结点S,那么在复制链表中,对应的N‘应该指向S‘。
时间复杂度:O(N)
方法三
在不使用辅助空间的情况下实现O(N)的时间效率。
- 根据原始链表的每个结点N创建对应的N‘,然后将N‘通过pNext接到N的后面;
- 设置复制出来的结点的pSibling。假设原始链表上的N的pSibling指向结点S,那么其对应复制出来的N‘是N->pNext指向的结点,同样S‘也是结点S->pNext指向的结点。
- 把长链表拆分成两个链表,把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。
hash方法
struct ComplexListNode{ int val; ComplexListNode* pNext; ComplexListNode* pSibling; ComplexListNode():val(0),pNext(NULL),pSibling(NULL){}; }; typedef std::map<ComplexListNode*,ComplexListNode*> MAP; ComplexListNode* CloneNodes(ComplexListNode* pHead,MAP &hashNode){ ComplexListNode* pNode=new ComplexListNode(); ComplexListNode* p=pNode; ComplexListNode* tmp; while(pHead!=NULL){ tmp=new ComplexListNode(); tmp->val=pHead->val; p->pNext=tmp; hashNode[pHead]=tmp; pHead=pHead->pNext; p=p->pNext; } return pNode->pNext; } void SetSiblings(ComplexListNode* pHead,ComplexListNode* pCopy,MAP &hashNode){ while(pCopy!=NULL){ pCopy->pSibling=hashNode[pHead->pSibling]; pCopy=pCopy->pNext; pHead=pHead->pNext; } } ComplexListNode* ComplexListCopy(ComplexListNode* pHead){ ComplexListNode* pCopy; MAP hashNode; pCopy=CloneNodes(pHead,hashNode); SetSiblings(pHead,pCopy,hashNode); return pCopy; }
复制连接的方法
#include <iostream> using namespace std; struct node { int data; struct node *next,*sibling; }; class Solution { public: Solution(); void create(); void print(); node *clone(node *head); void clone_node(node *head); void con_sib_node(node *head); node *recon_node(node *head); node *head; }; Solution::Solution() { head=new node(); head->next=nullptr; head->sibling=nullptr; head->data=0; } void Solution::create() { if(head==nullptr) return; auto t=head; int x; while(1) { cin>>x; if(x) { t->next=new node(); t=t->next; t->sibling=nullptr; t->data=x; t->next=nullptr; } else { t->next=nullptr; t->sibling=nullptr; break; } } } void Solution::print() { auto n=head->next; while(n) { cout<<n->data<<endl; n=n->next; } } node *Solution::clone(node *head) { clone_node(head); con_sib_node(head); return recon_node(head); } void Solution::clone_node(node *head) { node *n=head->next; while(n) { node *clone=new node(); clone->data=n->data; clone->next=n->next; clone->sibling=nullptr; n->next=clone; n=clone->next; } } void Solution::con_sib_node(node *head) { node *n=head->next; while(n) { node *clone=n->next; if(n->sibling) clone->sibling=n->sibling->next; n=clone->next; } } node *Solution::recon_node(node *head) { node *n=head->next; node *h_clone=nullptr; node *n_clone=nullptr; if(n) { h_clone=n_clone=n->next; n->next=n_clone->next; n=n->next; } while(n) { n_clone->next=n->next; n_clone=n_clone->next; n->next=n_clone->next; n=n->next; } return h_clone; } int main() { Solution s; s.create(); node *h=s.clone(s.head); return 0; }
以上是关于复杂链表的复制的主要内容,如果未能解决你的问题,请参考以下文章