5.LeetCode.138. Copy List with Random Pointer【复杂链表的复制】

复杂链表的复制【138】(medium)

#include <iostream>
#include <map>
#include <vector>

using namespace std;

class Node {
  public:
    int val;
    Node *next;
    Node *random;

    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};

class Solution {
  public:
    /*
     * 时间复杂度:O(N)
     * 空间复杂度:O(1)
     */
    Node *copyRandomList(Node *head) {
        Node *ptr = head;
        Node *tmp_node = NULL;
        if (head == NULL)
            return NULL;

        //创建相邻结点
        // Inserting the cloned node just next to the original node.
        // If A->B->C is the original linked list,
        // Linked list after weaving cloned nodes would be A->A'->B->B'->C->C'
        while (ptr) {
            tmp_node = ptr->next;
            ptr->next = new Node(ptr->val); // ptr后创建新结点
            ptr->next->next = tmp_node;
            // ptr = ptr->next->next;
            ptr = tmp_node;
        }
        ptr = head;

        // 遍历新链表,修改新结点的random指针
        // Now link the random pointers of the new nodes created.
        // Iterate the newly created list and use the original nodes' random
        // pointers, to assign references to random pointers for cloned nodes.

        while (ptr) {
            if (ptr->random != NULL) {
                // 新链表 random 结点, 连接
                ptr->next->random = ptr->random->next;
            } else {
                ptr->next->random = NULL;
            }
            ptr = ptr->next->next; // 循环新链表
        }

        // 修改链表结构
        // Unweave the linked list to get back the original linked list and the
        // cloned list.
        // i.e. A->A'->B->B'->C->C' would be broken to A->B->C and A'->B'->C'

        Node *ptr_old_list = head;       // A->B->C
        Node *ptr_new_list = head->next; // A'->B'->C'
        Node *result = head->next;
        while (ptr_old_list != NULL) {
            ptr_old_list->next = ptr_old_list->next->next;
            if (ptr_new_list->next != NULL)
                ptr_new_list->next = ptr_new_list->next->next;
            else
                ptr_new_list->next = NULL;
            ptr_old_list = ptr_old_list->next;
            ptr_new_list = ptr_new_list->next;
        }
        return result;
    }

    // Node* copyRandomList(Node* head) {
    //     // 方法一、使用map映射
    //     map<Node*, int> node_map;  // 地址节点map
    //     vector<Node*> node_vec;    // vector 存储节点地址
    //     Node* ptr = head;
    //     int i = 0;
    //     while (ptr) {
    //         // 新链表结点push到node_vec, 生成新链表 节点位置-->地址的 map映射
    //         node_vec.push_back(new Node(ptr->val));
    //         node_map[ptr] = i;  // 记录原始 链表地址--> 节点位置 node_map映射
    //         ptr = ptr->next;
    //         i++;  // 记录节点位置
    //     }
    //     node_vec.push_back(0);  // 处理最后一个节点
    //     ptr = head;
    //     i = 0;
    //     while (ptr) {  // 再次遍历原始链表 连接新链表的next、random指针
    //         node_vec[i]->next = node_vec[i + 1];  // 连接新链表next指针
    //         if (ptr->random) {                    // random指针不为空
    //             int id = node_map[ptr->random];   // 从node_map中查找
    //             // 原链表random指针指向的位置即id
    //             // 链接新链表random指针
    //             node_vec[i]->random = node_vec[id];
    //         }
    //         ptr = ptr->next;
    //         i++;
    //     }
    //     return node_vec[0];
    // }
};

int main() {
    Node a(1);
    Node b(2);
    Node c(3);
    Node d(4);
    Node e(5);

    a.next = &b;
    b.next = &c;
    c.next = &d;
    d.next = &e;

    a.random = &c;
    b.random = &d;
    c.random = &c;
    e.random = &d;

    Solution solve;
    Node *head = solve.copyRandomList(&a);
    while (head) {
        cout << "node = " << head->val;
        if (head->random)
            cout << "rand = " << head->random->val << endl;
        else
            cout << "rand = NULL" << endl;
        head = head->next;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值