GH1995 / leetcode-test-and-run

方便 leetcode 刷题的小工具
GNU General Public License v2.0
0 stars 0 forks source link

138. Copy List with Random Pointer 拷贝带有随机指针的链表 #29

Open GH1995 opened 5 years ago

GH1995 commented 5 years ago

138. Copy List with Random Pointer

Difficulty: Medium

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a of the list.

Example 1:

Input:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}

Explanation:
Node 1's value is 1, both of its next and random pointer points to Node 2.
Node 2's value is 2, its next pointer points to null and its random pointer points to itself.

Note:

  1. You must return the copy of the given head as a reference to the cloned list.
GH1995 commented 5 years ago

链表的循环值是cur

  1. 复制链表 node->next = cur->next
  2. 给随机指针赋值 cur->next->random = cur->random->next
  3. 拆分链表new_cur->next = cur->next
GH1995 commented 5 years ago
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    /*
     * 对链表进行三次扫描,第一次扫描对每个结点进行复制,然后把复制出来的新节点接在原结点的next,也就是让链表变成一个重复链表,就是新旧更替;第二次扫描中我们把旧结点的随机指针赋给新节点的随机指针,因为新结点都跟在旧结点的下一个,所以赋值比较简单,就是node.next.random = node.random.next,其中node.next就是新结点,因为第一次扫描我们就是把新结点接在旧结点后面。现在我们把结点的随机指针都接好了,最后一次扫描我们把链表拆成两个,第一个还原原链表,而第二个就是我们要求的复制链表。因为现在链表是旧新更替,只要把每隔两个结点分别相连,对链表进行分割即可。这个方法总共进行三次线性扫描,所以时间复杂度是O(n)。而这里并不需要额外空间,所以空间复杂度是O(1)。比起上面的方法,这里多做一次线性扫描,但是不需要额外空间,还是比较值的。
     */
    RandomListNode *copyRandomList(RandomListNode *head) {
        auto cur = head;
        while (cur) {
            auto node = new RandomListNode(cur->label);
            node->next = cur->next;
            cur->next = node;
            cur = node->next;
        }

        cur = head;
        while (cur) {
            if (cur->random) {
                cur->next->random = cur->random->next;
            }
            cur = cur->next->next;
        }

        // 拆分两个单链表
        RandomListNode dummy(-1);
        auto new_cur = &dummy;
        cur = head;
        while (cur) {
            new_cur->next = cur->next;
            new_cur = new_cur->next;
            cur->next = cur->next->next;
            cur = cur->next;
        }

        return dummy.next;
    }
};