牛客网《剑指Offer》编程 25.复杂链表的复制(优化的暴力法)

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

解题思路

这次试用优化之后的暴力法解题。

首先 遍历一次原链表,这次只复制next域。同时将原链表与复制链表中节点的一一对应关系,存储在map中。比如原链表中的节点为A,复制链表中对应的值相等的节点为A',map中的键值对就是<A,A'>。

再次遍历原链表,此时复制random域。此时命题是:遍历到了原链表中的某个节点,此时已知该节点的random域,根据map能够查到复制链表中对应的random域。该random域就是复制链表中的random域。

代码实现

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if (!pHead) {
			return nullptr;
		}
		RandomListNode* currNode = pHead;
		RandomListNode* newNode = nullptr, *preNode = nullptr, *newHead = nullptr;
		map<RandomListNode*, RandomListNode*> nodeMap;
		while (currNode) {
			newNode = new RandomListNode(currNode->label);
			nodeMap[currNode] = newNode;
			currNode = currNode->next;
			
			if (preNode == nullptr) {
				newHead = newNode;
			}
			else {
				preNode->next = newNode;
			}
			preNode = newNode;
		}
		newNode = newHead;
		currNode = pHead;
		while (currNode&&newNode) {
			RandomListNode* currRandom = currNode->random;
			RandomListNode* randomNode = nodeMap[currRandom];
			newNode->random = randomNode;
			currNode = currNode->next;
			newNode = newNode->next;
		}
		return newHead;
    }
};

测试用例

使用以下测试用例:

1.空链表

2.普通随机链表

3.random域指向自身的链表

4.只有一个节点的链表

5.存在两个节点护指的链表

测试代码和结果如下:

int main()
{
	//Test1:空链表
	RandomListNode* node = nullptr;
	//Test2:普通随机链表
	RandomListNode* node0 = new RandomListNode(0);
	RandomListNode* node1 = new RandomListNode(1);
	RandomListNode* node2 = new RandomListNode(2);
	RandomListNode* node3 = new RandomListNode(3);
	RandomListNode* node4 = new RandomListNode(4);
	node0->next = node1;
	node1->next = node2;
	node2->next = node3;
	node3->next = node4;
	node4->next = nullptr;
	node0->random = node2;
	node1->random = node4;
	node3->random = node1;
	//Test3:random域指向自身
	RandomListNode* node5 = new RandomListNode(5);
	RandomListNode* node6 = new RandomListNode(6);
	node5->next = node6;
	node6->next = nullptr;
	node5->random = node5;
	//Test4:只有一个节点的链表
	RandomListNode* node7 = new RandomListNode(7);
	node7->next = nullptr;
	node7->random = node7;
	//Test5:两个链表节点互相指,从而形成环状
	RandomListNode* node8 = new RandomListNode(8);
	RandomListNode* node9 = new RandomListNode(9);
	RandomListNode* node10 = new RandomListNode(10);
	RandomListNode* node11 = new RandomListNode(11);
	RandomListNode* node12= new RandomListNode(12);
	node8->next = node9;
	node9->next = node10;
	node10->next = node11;
	node11->next = node12;
	node12->next = nullptr;
	node9->random = node11;
	node11->random = node9;
	//判断是否是值相同的链表:先打印链表,再打印每个节点的random域。
	cout << "******************Test1:空链表测试******************" << endl;
	RandomListNode* ans = Clone(node);
	cout << "原链表:" << endl;
	print(node);
	cout << endl;
	cout << "复制链表:" << endl;
	print(ans);
	cout << "******************Test2:空链表测试******************" << endl;
	RandomListNode* ans0 = Clone(node0);
	cout << "原链表:" << endl;
	print(node0);
	cout << endl;
	cout << "复制链表:" << endl;
	print(ans0);
	cout << "******************Test3:random域指向自身链表测试******************" << endl;
	RandomListNode* ans1 = Clone(node5);
	cout << "原链表:" << endl;
	print(node5);
	cout << endl;
	cout << "复制链表:" << endl;
	print(ans1);
	cout << "******************Test4:只有一个节点的链表测试******************" << endl;
	RandomListNode* ans2 = Clone(node7);
	cout << "原链表:" << endl;
	print(node7);
	cout << endl;
	cout << "复制链表:" << endl;
	print(ans2);
	cout << "******************Test5:存在两个节点护指的链表测试******************" << endl;
	RandomListNode* ans3 = Clone(node8);
	cout << "原链表:" << endl;
	print(node8);
	cout << endl;
	cout << "复制链表:" << endl;
	print(ans3);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/eriHanami/article/details/82825471
今日推荐