【LeetCode】【链表】剑指 Offer 35. 复杂链表的复制 思路解析和代码

剑指 Offer 35. 复杂链表的复制

题目链接

个人思路

题意

本题考查的是链表的深拷贝和浅拷贝
ListNode* cur = head //是浅拷贝,cur与head共用一个地址
ListNode* cur = new ListNode()//是深拷贝,二者地址不同
此题的原链表和复制链表中,各自的指针(next和random)指向各自链表内数据的地址

思路

  1. 先复制next指针,构建出复制链
  2. 在根据原链中的random,在复制链中构造random

难点在于如何完成深拷贝,如何根据原链的random确定复制链中random的指向

暴力O(n2)

如何完成深拷贝:通过文章开头的new来创建节点

如何根据原链的random确定复制链中random的指向:

  • 从头遍历原链
    • 记录原链的当前节点的random
    • 从头遍历原链,得到random距离头结点的步数
    • 在复制链中找到相应步数对应的结点,让random指向它
哈希表——空间换时间O(n)
  • 用哈希表mp记录,mp[原链节点]=复制节点
  • 从头遍历原链
    • 记录原链的当前节点的random
    • mp中寻找对应的复制节点
    • 复制链的当前节点的random指向它

注意

个人思路代码

暴力
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == NULL){
            return NULL;
        }
        //复制next
        Node* cur = head;
        bool flag = false;//标记是否是复制链的头结点
        Node* ans, *pre;
        while(cur != NULL){
            //创建新节点
            Node* temp = new Node(cur->val);
            temp->next = NULL;
            temp->random = NULL;
            if(flag == false){//将复制链的头结点给ans
                flag = true;
                ans = temp;
                pre = ans;
            }else{
                pre->next = temp;
                pre = pre->next;
            }
            cur = cur->next;
        }
        //复制random
        Node* i = head;
        Node* copycur = ans;
        while(i != NULL){
            Node* rand = i->random;
            if(rand == NULL){
                copycur->random = NULL;
            }else{
                //记录原链的random距离头结点有多少步
                Node* j = head;
                int step = 0;
                while(j != NULL){
                    if(j == rand){
                        break;
                    }
                    step++;
                    j = j->next;
                }
                //在复制链中寻找相同的步数
                j = ans;
                while(step > 0){
                    j = j->next;
                    step--;
                }
                copycur->random = j;
            }
            i = i->next;
            copycur = copycur->next;
        }
        return ans;
    }
};
哈希表
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    unordered_map<Node*, Node*> mp;
    Node* copyRandomList(Node* head) {
        if(head == NULL){
            return NULL;
        }
        //复制next
        Node* cur = head;
        Node* pre, *ans;
        bool flag = false;
        while(cur != NULL){
            Node* temp = new Node(cur->val);
            mp[cur] = temp;
            if(flag == false){
                ans = temp;
                pre = ans;
                flag = true;
            }else{
                pre->next = temp;
                pre = pre->next;
            }
            cur = cur->next;
        }
        //通过hash复制random
        Node *i = head;
        Node *j = ans;
        while(i != NULL){
            Node* temp = i->random;
            if(temp != NULL){
                j->random = mp[temp];
            }
            i = i->next;
            j = j->next;
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值