原题来自书籍《剑指offer》,这是作者的该题的博客地址。
关于该题的题意就不再敖述,其大意有点类似C++中的深复制,需要另外的空间来保存复制的内容,而不是简单的将指针指向同一份内容。题目的分析在原博客中已有,尤其是作者推荐的第三种解法,很巧妙。不过最后生成的新链表其实是在原链表上断开并重新连接的,然后抓住新链表的头指针返回,因此在脑海里可以想象,其实“新链表”不是很干净的,因为还有一些原来的节点附在新链表节点上,只不过这些指针我们找不大访问不到了。
这里主要实现一下作者提到的第二种解法和第三种解法,在测试代码中生成十个节点的链表,为了便于测试,节点的sibing指针指向相隔一个节点的节点,即next的next。另外,为了区分复制出来的内容,我将复制的节点的val值都加上了10,便于区分。
节点node的结构如下:
struct node{ int val; node* next; node* sibling; };
int main() { // initial a linked list node* head = new node(); head->val = 1; head->next = NULL; head->sibling = NULL; node* lists = head; for (int i = 2; i <= NUM; ++i) { node* n = new node(); n->val = i; n->next = NULL; n->sibling = NULL; lists->next = n; lists = lists->next; } lists = head; while (lists->next) { lists->sibling = lists->next->next; lists = lists->next; }// end initial // print the orignal linked list lists = head; while (lists) { cout << lists->val << "->sibling = "; if (lists->sibling) cout << lists->sibling->val << endl; else cout << "NULL" << endl; lists = lists->next; } cout << endl; // end print // clone the list //node* newHead = clone1(head); node* newHead = clone2(head); // print the cloned linked list while (newHead) { cout << newHead->val << "->sibling = "; if (newHead->sibling) cout << newHead->sibling->val << endl; else cout << "NULL" << endl; newHead = newHead->next; }// end print }第二种解法采用哈希表的方式,clone1代码如下:
node* clone1(node* head) { if (!head) return NULL; unordered_map<node*, node*> container; node* newHead = NULL; node* lists = NULL; node* iter = head; while (iter) { node* tmp = new node(); tmp->val = iter->val + 10; tmp->next = NULL; tmp->sibling = NULL; if (!newHead) { newHead = tmp; lists = tmp; } else { lists->next = tmp; lists = lists->next; } container[iter] = lists; iter = iter->next; } iter = head; while (iter) { container[iter]->sibling = container[iter->sibling]; iter = iter->next; } return newHead; }第三种解法,原作者的思路,自己理解之后码一遍:
void buildNextPtr(node* head) { node* lists = head; while (lists) { node* tmp = new node(); tmp->val = lists->val + 10; tmp->next = lists->next; tmp->sibling = NULL; lists->next = tmp; lists = lists->next->next; } } void buildSiblingPtr(node* head) { node* lists = head; while (lists) { if (lists->sibling) lists->next->sibling = lists->sibling->next; lists = lists->next->next; } } node* splitLinkedList(node* head) { if (!head) return NULL; node* newHead = head->next; node* lists = newHead; while (lists && lists->next) { lists->next = lists->next->next; lists = lists->next; } return newHead; } node* clone2(node* head) { buildNextPtr(head); buildSiblingPtr(head); return splitLinkedList(head); }完整代码在最后,以下是测试运行的结果:
完整代码:
#include <iostream> #include <unordered_map> using namespace std; #define NUM 10 struct node{ int val; node* next; node* sibling; }; node* clone1(node*); node* clone2(node*); int main() { // initial a linked list node* head = new node(); head->val = 1; head->next = NULL; head->sibling = NULL; node* lists = head; for (int i = 2; i <= NUM; ++i) { node* n = new node(); n->val = i; n->next = NULL; n->sibling = NULL; lists->next = n; lists = lists->next; } lists = head; while (lists->next) { lists->sibling = lists->next->next; lists = lists->next; }// end initial // print the orignal linked list lists = head; while (lists) { cout << lists->val << "->sibling = "; if (lists->sibling) cout << lists->sibling->val << endl; else cout << "NULL" << endl; lists = lists->next; } cout << endl; // end print // clone the list //node* newHead = clone1(head); node* newHead = clone2(head); // print the cloned linked list while (newHead) { cout << newHead->val << "->sibling = "; if (newHead->sibling) cout << newHead->sibling->val << endl; else cout << "NULL" << endl; newHead = newHead->next; }// end print } node* clone1(node* head) { if (!head) return NULL; unordered_map<node*, node*> container; node* newHead = NULL; node* lists = NULL; node* iter = head; while (iter) { node* tmp = new node(); tmp->val = iter->val + 10; tmp->next = NULL; tmp->sibling = NULL; if (!newHead) { newHead = tmp; lists = tmp; } else { lists->next = tmp; lists = lists->next; } container[iter] = lists; iter = iter->next; } iter = head; while (iter) { container[iter]->sibling = container[iter->sibling]; iter = iter->next; } return newHead; } void buildNextPtr(node* head) { node* lists = head; while (lists) { node* tmp = new node(); tmp->val = lists->val + 10; tmp->next = lists->next; tmp->sibling = NULL; lists->next = tmp; lists = lists->next->next; } } void buildSiblingPtr(node* head) { node* lists = head; while (lists) { if (lists->sibling) lists->next->sibling = lists->sibling->next; lists = lists->next->next; } } node* splitLinkedList(node* head) { if (!head) return NULL; node* newHead = head->next; node* lists = newHead; while (lists && lists->next) { lists->next = lists->next->next; lists = lists->next; } return newHead; } node* clone2(node* head) { buildNextPtr(head); buildSiblingPtr(head); return splitLinkedList(head); }