medium 剑指 Offer 复杂链表的复制 哈希表 拼接+拆分

在这里插入图片描述

在这里插入图片描述


哈希表:

第一次遍历原链表(已用 next 指针连接,用 while(cur != nullptr)循环 cur = cur->next 遍历),复制遍历过的节点(创建新节点)。

c++


class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr){
            return nullptr;
        }
        // 复制节点 值
        Node* cur = head;  // 创建新指针(用于复制链表), 指向头指针
        unordered_map<Node*, Node*> mp;  // 哈希表<键,对> <旧节点, 复制后新节点(节点值)> 
        while(cur != nullptr){
            mp[cur] = new Node(cur->val);  // 复制(创建新节点Node,放入原节点值)
            cur = cur->next;  // 继续复制下一个节点 <指针, 值>
        }
        cur = head; 
        // 复制节点 next 和 random
        while(cur != nullptr){  // mp[cur] 即刚刚创建的 new Node
            mp[cur]->next = mp[cur->next];  // ->next 连接下一个节点 mp[cur->next]
            mp[cur]->random = mp[cur->random];
            cur = cur->next;
        }

        return mp[head];  // 返回新链表的头节点
    }
};

python


class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head:
            return None
        dic = {}
        cur = head
        while cur:
            dic[cur] = Node(cur.val)
            cur = cur.next
        cur = head
        while cur:  # dic[cur] = Node(cur.val)
            dic[cur].next = dic.get(cur.next)   # 如果用 = dic[cur.next], 如果cur.next = null则keyerror  
            dic[cur].random = dic.get(cur.random)
            cur = cur.next

        return dic[head]

在这里插入图片描述


拼接+拆分:

c++ 创建新节点 Node* tmp = new Node(cur->val);
python 创建新节点 tmp = Node(cur.val)

c++


class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr){
            return nullptr;
        }
        // 插入(复制)
        Node* cur = head;   
        while(cur != nullptr){
            Node* tmp = new Node(cur->val);  // 创建新节点new Node,节点放入数据值
            tmp->next = cur->next;
            cur->next = tmp;
            cur = tmp->next;  // 复制下一个节点
        }
        // 新节点添加random指针     
        cur = head;
        while(cur != nullptr){
            if(cur->random != nullptr){  // 只遍历旧节点
                // cur->next->random 新插入节点, cur->random->next 原节点的random节点的复制节点
                cur->next->random = cur->random->next;
            }
            cur = cur->next->next; // cur->next是复制的节点, cur->next->next是原节点的下个节点
        }
        // 拆分两链表
        cur = head->next;  // cur从复制节点开始
        Node* pre = head;  // pre从头节点开始
        Node* res = head->next;  // res原始第一个复制节点
        while(cur->next != nullptr){  // 复制后链表最后一个是复制节点
            pre->next = pre->next->next;  // pre一直指向原链表节点
            cur->next = cur->next->next;  // cur一直指向复制节点
            pre = pre->next;
            cur = cur->next;
        }
        pre->next = nullptr; // 单独处理原链表尾节点
        return res;      // 返回新链表头节点
    }
};

python


"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head:
            return None
        cur = head
        # 复制节点(插入节点)
        while cur:
            tmp = Node(cur.val)  # 创建新节点,并加入节点值
            tmp.next = cur.next
            cur.next = tmp
            cur = tmp.next
        # 构建各新节点的 random 指向
        cur = head
        while cur:
            if cur.random:  # 只处理链表原节点
                cur.next.random = cur.random.next
            cur = cur.next.next

        # 拆分两链表
        pre = head
        res = cur = head.next
        while cur.next:  # 链表尾结点是复制节点
            pre.next = pre.next.next  # pre只遍历原链表节点
            cur.next = cur.next.next  # cur只遍历原链表复制节点
            pre = pre.next
            cur = cur.next
        pre.next = None # 单独处理原链表尾结点
        
        return res

在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值