LeetCode138 复制带随机指针的链表(思维)

题目链接:leetcode138

题面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意

构造一个和原链表一模一样的链表,包括 random 指针。注意的是,操作结束后,原链表的结构不能被破坏。

解题思路

map

根据结构,我们可以先构造出和原链表一模一样的链表,并使每个节点一一对应,这边可以使用一个 map 。然后遍历原链表的所有节点,对于原链表的random 指针我们可以根据查询 map 的内容进行相应的 random 指针修改。

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度 O ( n ) O(n) O(n)。把 map 改成 HashMap 可以降低时间复杂度。

random 指针再利用

实际上,对于原链表的每个节点,我们创建新链表后可以使 random 指针和它一致,这样原链表的节点的 random 指针就可以腾挪出来指向新创建的节点。如此一来,法一的映射关系我们就建立完成,我们可以遍历一遍新链表,让它的 random 指针修改为它指向的原链表的节点 random 指针所指的内容,实际上,这部操作相当于我们进行查 map 的工作,当然,如果指向为空就没必要进行操作。

但是,问题来了,原链表的结构如何修复?显然,如果修改了新链表的 random 指针,原链表的 random 就断掉了。

这里我们有两种做法,一个是利用递归或者栈,把原链表中的 random 修改回去,并且能够夹带着把新链表一块修改。但是空间复杂度为 O ( n ) O(n) O(n)

另一种做法就是再复制一块内存专门存原 random 指针内容,同样空间复杂度为 O ( n ) O(n) O(n)

时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)

大致思路图如下,其中虚线表示原链表的 random 指针原来的指向:
在这里插入图片描述

next 指针修改

思路来自于官方题解,对于原链表的每个节点,在其后面插入一个新节点;第二次遍历链表修改每个新结点的 random 指针;第三次修改每个节点的 next 指针,最终会让奇数和偶数的节点串起来分别形成两个链表。算法结束。

时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)

代码实现

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 head;
        Node* curx=head, *newHead, *cury, *tmp, *tmpHead;
        
        tmp=createNode(tmpHead, head);
        cury=createNode(newHead, head);
        while (true) {
            curx->random=cury;
            curx=curx->next;
            if (curx == NULL) break;
            tmp=createNode(tmp->next, curx);
            cury=createNode(cury->next, curx);
        }
        
        for (cury=newHead, curx=head; curx != NULL; cury=cury->next, curx=curx->next){
            if (cury->random != NULL) {
                cury->random=cury->random->random;
            }
        }
        
        for (tmp=tmpHead, curx=head; curx != NULL; curx=curx->next) {
            curx->random=tmp->random;
            tmp=tmp->next;
            delete tmpHead;
            tmpHead=tmp;
        }
        
        return newHead;
    }
    
    Node* createNode(Node*& target, Node* source) {
        target=new Node(source->val);
        target->next=source->next;
        target->random=source->random;
        return target;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值