题目和思路来自剑指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;
}
测试用例如方法一,完。