[LeetCode] Copy List with Random Pointer
http://oj.leetcode.com/problems/copy-list-with-random-pointer/我用hash表ac的, 但是有更优雅的方法, 我是沙茶, 我想不出, 又看了题解, 题解的方法我总结如下:
每生成一个新结点, 就连到相应旧结点的next指针上, 这样形成了原链表和新链表每个结点依次先后相邻的一条链表,相当于一个合并的过程. 也许这步让人不明所以, 那么接下来的步骤就是关键, 把每个新结点的random指针指向该新结点前面那个旧节点的random指针的next, 这句话有点绕, 其实画个图更好理解. 懒的画图了, 使劲看会明白的. 最后一步就是把这个合并后的链表中的新链表分离出来,得到最终答案. 其实这个算法的原理就是建立旧链表结点和新链表结点的关系, 方便通过旧结点快速找到新结点. 我们最开始思考这道题的时候 要知道 这道题的瓶颈在于如何确定旧结点random指针所指向的旧结点对应着哪一个新结点, 如何建立旧节点和新结点的联系, 所以会自然而然的想到将新旧节点通过指针连起来, 而单链表只有一个指针, 不可能分出多路, 所以就只能把两个链表相邻串在一起形成一个链表.
下面代码是用hash实现的, 并不是我上面讲述的优雅算法的实现, 所以很丑.
class Solution { public: RandomListNode *copyRandomList(RandomListNode *head) { // IMPORTANT: Please reset any member data you declared, as // the same Solution instance will be reused for each test case. if (head == NULL) { return NULL; } unordered_map<RandomListNode*, int> m; RandomListNode* n[20480] = {0}; RandomListNode* newHead = new RandomListNode(head->label); m[head] = 0; n[0] = newHead; RandomListNode* pNode = head->next; RandomListNode* pNewNode = newHead; RandomListNode* pPreNewNode = newHead; int index = 1; while (pNode) { m[pNode] = index; pNewNode = new RandomListNode(pNode->label); n[index] = pNewNode; pPreNewNode->next = pNewNode; pPreNewNode = pNewNode; pNode = pNode->next; index++; } index = 0; pNewNode = newHead; pNode = head; while(pNewNode) { if (pNode->random == NULL) { pNewNode = pNewNode->next; pNode = pNode->next; continue; } int i = m[pNode->random]; pNewNode->random = n[i]; pNewNode = pNewNode->next; pNode = pNode->next; } return newHead; } };