题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
分析:因为链表有两个指针,一个next指针,一个特殊指针,所以我们如果采取暴力的方式,那么我们每次寻找特殊指针的节点都需要O(n)的时间,再配上外面的链表遍历,那么复杂度将达到O(n^2),这是不可以接受的。
优化:1.由于时间很大花费到了特殊指针寻找当前节点的过程中,所以我们如果采用一个哈希表来存储一下原来的节点到现在节点的映射,那么我们的寻找时间将变为O(1),这样一个for遍历就优化好了,时间复杂度为O(n),同时增加了O(n)的空间。
//使用哈希表,用空间来换取时间,时间复杂度为O(n),空间复杂度为O(n)
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
private:
map<RandomListNode*,RandomListNode*>Hash;
public:
Solution()
{
Hash.clear();
}
~Solution()
{
}
RandomListNode* ConstructMap(RandomListNode* pHead)
{
//对原有链表进行遍历并进行哈希表的构建
if(pHead==nullptr) return nullptr;
RandomListNode* Org = pHead;
RandomListNode* pre = nullptr;
RandomListNode* pNewHead = nullptr;
while(Org!=nullptr)
{
RandomListNode* pNode = new RandomListNode(Org->label);
Hash.insert(make_pair(Org,pNode));
Org = Org->next;
if(pre==nullptr) {
pre = pNode;
pNewHead = pNode;
}
else {
pre->next = pNode;
pre = pNode;
}
}
return pNewHead;
}
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead==nullptr) return nullptr;
RandomListNode* newHead = ConstructMap(pHead);
//得到哈希表,并初步构建起了next指针,下一步是构建特殊指针
RandomListNode* pNode = pHead;
RandomListNode* pNewNode = newHead;
while(pNode!=nullptr)
{
//查找特殊指针
if(pNode->random==nullptr) {
pNode = pNode->next;
pNewNode = pNewNode->next;
continue;
}
RandomListNode* This = pNode->random;
RandomListNode* now = Hash[This];
pNewNode->random = now;
pNewNode = pNewNode->next;
pNode = pNode->next;
}
return newHead;
}
};
2.三函数法 在原链表上进行操作,不需要开辟辅助空间
具体移步:https://blog.youkuaiyun.com/qq_21997625/article/details/84378436
代码:
//不使用额外空间换取时间复杂度,空间复杂度O(1),时间复杂度O(n)
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
Solution()
{
}
~Solution()
{
}
void InsertList(RandomListNode* pHead)
{
if(pHead==nullptr) return;
RandomListNode* pNode = pHead;
while(pNode!=nullptr)
{
RandomListNode* insertListNode = new RandomListNode(pNode->label);
insertListNode->next = insertListNode->random = nullptr;
RandomListNode* temp = pNode->next;
pNode->next = insertListNode;
insertListNode->next = temp;
pNode = temp;
}
}
void InsertSpecial(RandomListNode* pHead)
{
if(pHead==nullptr) return;
// 找到每一个偶数节点所指向的特殊节点
RandomListNode* pNode = pHead;
while(pNode!=nullptr)
{
RandomListNode* pCloned = pNode->next;
if(pNode->random==nullptr) {
pNode = pCloned->next;
pCloned->random = nullptr;
continue;
}
RandomListNode* now = pNode->random;
pCloned->random = now->next;
pNode = pCloned->next;
}
}
RandomListNode* subList(RandomListNode* pHead)
{
//拆分偶数节点
if(pHead==nullptr) return nullptr;
RandomListNode* pNode = pHead;
RandomListNode* pClonedHead = nullptr;
RandomListNode* pClonedNode = nullptr;
if(pNode!=nullptr)
{
pClonedHead = pClonedNode = pNode->next;
pNode->next = pClonedNode->next;
pNode = pNode->next;
}
while(pNode!=nullptr)
{
pClonedNode->next = pNode->next;
pClonedNode = pClonedNode->next;
pNode->next = pClonedNode->next;
pNode = pNode->next;
}
return pClonedHead;
}
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead==nullptr) return nullptr;
//1.在原链表每一个节点后面插一个复制的节点
InsertList(pHead);
//2.添加特殊指针
InsertSpecial(pHead);
//3.拆分长链表 得到偶数节点的内容
return subList(pHead);
}
};