[剑指offer-35]复杂链表的复制

[35]复杂链表的复制

1.题目

请实现一个函数可以复杂复杂链表

在复杂链表中,每一个节点除了有一个指针指向下一个节点,还有一个额外的指针指向链表中的任意节点或者null

在这里插入图片描述

图中实线箭头表示next指针,虚线箭头表示random指针,为了简答起见指向nullptr的指针没有画出

2.分析

  • 函数结束后原链表要与输入时保持一致

3.思路

【1】.一般思路

  1. 复杂原链表中的每一个节点,并用next 链接起来
  2. 设置每一个节点的random指针
    • 对于一个含有 n 个节点的链表,定位每一个random都需要从链表头节点开始经过 O ( n ) O(n) O(n)步才能找到,因此总的时间复杂度是 O ( n 2 ) O(n^2) O(n2)

【2】.利用哈希表用空间换时间

  1. 复制原链表上的每一个节点 N 创建 N’,并用next链接起来,同时我们把 <N,N’>的配对信息放到哈希表中;
  2. 设置复制链表上的random。如果原始链表中节点 N 的 random指向 S ,那么复制链表中,对应的 N’ 应该指向 S’ 。
    • 由于有了 哈希表 ,我们可以用 O ( 1 ) O(1) O(1)的时间,根据 S 找到 S’。
    • 我们以 O ( n ) O(n) O(n)的空间复制度把时间复制度由 O ( n 2 ) O(n^2) O(n2) 降到了 O ( n ) O(n) O(n)

【3】

  1. 复制原始链表中任意节点 N 并创建 N’ ,再把 N’ 链接到 N 的后面

    在这里插入图片描述

  2. 设置复制出来的节点的random

    在这里插入图片描述

  3. 把这个长链表拆分为两个链表

    • 奇数位置用next链接,就是原链表
    • 偶数位置用next链接,就是复制出来的链表

    在这里插入图片描述

思路动画

在这里插入图片描述

4.代码

/**
 * Definition for singly-linked list with a random pointer.
 * struct ListNode {
 *     int val;
 *     ListNode *next, *random;
 *     ListNode(int x) : val(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        
        for(auto p = head; p;)  // 复制链表
        {
            auto pCopy = new ListNode(p->val);
            auto temp = p->next;
            
            p->next = pCopy;
            pCopy->next = temp;
            
            p = temp; // 移动节点
        }
        
        for(auto p = head; p; p = p->next->next)  // 设置复制出来节点的random
        {
            if(p->random)
                p->next->random = p->random->next;
        }
        
        auto dummy = new ListNode(-1);
        auto cur = dummy;
        
        auto p = head;
        while(p)
        {
        cur->next = p->next;
        cur = cur->next;  // cur 现在指向复制节点
        p = cur->next; // 还原链表
        }
        return dummy->next;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值