题目和思路来自剑指Offer
题目
举例
思路:难点是怎么确定兄弟指针的指向。
思路(1)使用Map确定兄弟指针的指向
如上例,输入数据为 A,B,C,D、E
建立的map:
A - A'
B - B'
...
E - E'
初始化兄弟结点的值:
以结点A为例,要寻找结点A'的兄弟结点D'
遍历已有链表的结点A时,找到其兄弟结点D,之后根据Map,获得D',这里D'就是新链表结点A'的兄弟结点
这里,空间复杂度为O(n),时间复杂度为O(n),假设map查找时间为O(1)。
代码
#include <iostream> #include <map> #include <assert.h> using namespace std; struct Node { int m_nValue; Node* m_pNext; Node* m_pSbling; }; /*根据已知链表,创建新链表,此时兄弟指针赋空*/ Node* CreatNewList(Node* pHead,map<Node*,Node*>& mapCloneNode) { Node* pNewHead = NULL; Node* pLastNew = NULL; Node* pCur = pHead; while (pCur) { //创建链表 Node* pNewNode = new Node; pNewNode->m_nValue = pCur->m_nValue; pNewNode->m_pSbling = NULL; pNewNode->m_pNext = NULL; if (!pNewHead) { pNewHead = pNewNode; } else { pLastNew->m_pNext = pNewNode; } pLastNew = pNewNode; //把链表插入map mapCloneNode.insert(make_pair(pCur,pNewNode)); pCur = pCur->m_pNext; } return pNewHead; } /*根据A,查找A'*/ Node* FindNew(map<Node*,Node*>& mapCloneNode,Node* pNode) { if (pNode == NULL) { return NULL; } map<Node*,Node*>::iterator itCur = mapCloneNode.find(pNode); if (itCur != mapCloneNode.end()) { return itCur->second; } else { return NULL; } } /*根据A,查找A的兄弟*/ void FindSbling(map<Node*,Node*>& mapCloneNode,Node* pHead,Node* pNewHead) { Node* pCur = pHead; Node* pCurSbling = NULL; Node* pCurNew = pNewHead; while(pCur) { pCurNew->m_pSbling = FindNew(mapCloneNode,pCur->m_pSbling); pCur = pCur->m_pNext; pCurNew = pCurNew->m_pNext; } } /*主函数*/ Node* Clone(Node* pHead) { assert(pHead); map<Node*,Node*> mapCloneNode; Node* pNewHead = CreatNewList(pHead,mapCloneNode); //创建新链表,但兄弟指针赋空 FindSbling(mapCloneNode,pHead,pNewHead);//获得兄弟指针 return pNewHead; } void Print(Node* pHead) { Node* pCur = pHead; while(pCur) { cout<<pCur->m_nValue<<" "; if (pCur->m_pSbling) { cout<<pCur->m_pSbling->m_nValue<<endl; } else { cout<<0<<endl; } pCur = pCur->m_pNext; } cout<<endl; } Node* CreatList() { int nLen = 0; int nSblingData = 0; cin >> nLen; //创建结点 Node* pHead = NULL; Node* pNew = NULL; Node* pLast = NULL; for (int i = 0;i < nLen;i++) { pNew = new Node; cin>>pNew->m_nValue; pNew->m_pNext = NULL; pNew->m_pSbling = NULL; if (pHead == NULL) { pHead = pNew; } else { pLast->m_pNext = pNew; } pLast = pNew; } //创建兄弟 Node* pCur = pHead; Node* pCurTmp = pHead; while(pCur) { cin>>nSblingData;//接受兄弟的下标 pCurTmp = pHead; if (nSblingData == 0) { pCur->m_pSbling = NULL; } else { while(pCurTmp && nSblingData != pCurTmp->m_nValue) { pCurTmp = pCurTmp->m_pNext; } assert(pCurTmp); pCur->m_pSbling = pCurTmp; } pCur = pCur->m_pNext; } return pHead; } int main() { Node* pHead = NULL; Node* pNewHead = NULL; pHead = CreatList(); Print(pHead); pNewHead = Clone(pHead); Print(pHead); system("pause"); return 1; }这里借用王道论坛的测试用例:题目1524:复杂链表的复制
附加带环的测试用例
输入:
5
1 2 3 4 5
3 2 1 5 4
输出:
1 3
2 2
3 1
4 5
5 4
思路(2)在旧链表中创建新链表,之后再从旧链表中拆分得到新链表
具体分为三步:
(1)在旧链表中创建新链表,此时不处理新链表的兄弟结点
(2)根据旧链表的兄弟结点,初始化新链表的兄弟结点
(3)从旧链表中拆分得到新链表
代码:
#include <iostream> #include <map> #include <assert.h> using namespace std; struct Node { int m_nValue; Node* m_pNext; Node* m_pSbling; }; /*根据已知链表,创建新链表,此时兄弟指针赋空*/ void CreatNewList(Node* pHead) { assert(pHead); Node* pCur = pHead; while (pCur) { //创建链表 Node* pNewNode = new Node; pNewNode->m_nValue = pCur->m_nValue; pNewNode->m_pSbling = NULL; pNewNode->m_pNext = pCur->m_pNext; pCur->m_pNext = pNewNode; pCur = pCur->m_pNext->m_pNext; } } /*根据A,查找A的兄弟*/ void InitSbling(Node* pHead) { assert(pHead); Node* pCur = pHead; Node* pCurNext = NULL; while(pCur) { pCurNext = pCur->m_pNext; if (pCur->m_pSbling) { pCurNext->m_pSbling = pCur->m_pSbling->m_pNext; } pCur = pCur->m_pNext->m_pNext; } } Node* SeparateList(Node* pHead) { assert(pHead); Node* pNewHead = NULL; Node* pCur = pHead; Node* pLastNew = NULL; while(pCur) { if (pNewHead == NULL) { pNewHead = pCur->m_pNext; } else { pLastNew->m_pNext = pCur->m_pNext; } pLastNew = pCur->m_pNext; pCur->m_pNext = pCur->m_pNext->m_pNext; pCur = pCur->m_pNext; } return pNewHead; } /*主函数*/ Node* Clone(Node* pHead) { assert(pHead); CreatNewList(pHead); //创建新链表,但兄弟指针赋空 InitSbling(pHead); return SeparateList(pHead); } void Print(Node* pHead) { Node* pCur = pHead; while(pCur) { cout<<pCur->m_nValue<<" "; if (pCur->m_pSbling) { cout<<pCur->m_pSbling->m_nValue<<endl; } else { cout<<0<<endl; } pCur = pCur->m_pNext; } cout<<endl; } Node* CreatList() { int nLen = 0; int nSblingData = 0; cin >> nLen; //创建结点 Node* pHead = NULL; Node* pNew = NULL; Node* pLast = NULL; for (int i = 0;i < nLen;i++) { pNew = new Node; cin>>pNew->m_nValue; pNew->m_pNext = NULL; pNew->m_pSbling = NULL; if (pHead == NULL) { pHead = pNew; } else { pLast->m_pNext = pNew; } pLast = pNew; } //创建兄弟 Node* pCur = pHead; Node* pCurTmp = pHead; while(pCur) { cin>>nSblingData;//接受兄弟的下标 pCurTmp = pHead; if (nSblingData == 0) { pCur->m_pSbling = NULL; } else { while(pCurTmp && nSblingData != pCurTmp->m_nValue) { pCurTmp = pCurTmp->m_pNext; } assert(pCurTmp); pCur->m_pSbling = pCurTmp; } pCur = pCur->m_pNext; } return pHead; } int main() { Node* pHead = NULL; Node* pNewHead = NULL; pHead = CreatList(); Print(pHead); pNewHead = Clone(pHead); Print(pHead); system("pause"); return 1; }测试用例如方法一,完。