剑指-35


题目描述

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

本题的两个解法都很有意思,mark一下
【重点学习第二种方法】

一、解法一:哈希表法

利用哈希表建立原链表head到新链表result的映射

第一趟遍历:
根据head的val创建新链表节点
将 head:result 的键值对放到HashMap中

第二趟遍历:
根据head等到他的random节点hRan
根据hRan得到他对应的value, 即新链表这个节点的 rRan

public Node copyRandomList(Node head) {
        if (head == null) return null;
        Map<Node, Node> map = new HashMap<>();
        Node temp = head;
        Node result = new Node(-1), cur = result;

        while (head != null) {
            cur.next = new Node(head.val);
            map.put(head, cur.next);
            cur = cur.next;
            head = head.next;
        }

        cur = result.next;
        while (temp != null) {
            Node ran = temp.random;
            if (ran != null) {
                cur.random = map.get(ran);
            }
            cur = cur.next;
            temp = temp.next;
        }

        return result.next;
    }

时复:o(n) 两趟遍历
空复:o(n) 对每个节点建立一个映射哈希表

二、解法二:插入法

第一趟:在原链表head的每个节点cur的后面建立一个与cur等val的新节点node;
第二趟:根据cur.random 为node.random赋值为 cur.random.next; 【注意判空】
第三躺:将cur与node的next指针还原【注意最后一个cur指针必须指向空】

public Node copyRandomList(Node head) {
        if (head == null) return null;
        
        Node result = null, cur = head;;
        while (cur != null) {
            Node temp = new Node(cur.val);
            temp.next = cur.next;
            cur.next = temp;
            cur = temp.next;
        }
        
        cur = head;
        result = head.next;
        Node node = result;
        while (cur != null) {
          Node temp = cur.next.next;
          if (cur.random != null) {
              cur.next.random = cur.random.next;
          }
            cur = temp;
        }
        cur = head;
        while (node.next != null) {
            cur.next = node.next;
            node.next = node.next.next;
            node = node.next;
            cur = cur.next;
        }
        cur.next = null;
        
        return result;
    }

时复:O(n) 三趟遍历
空复:O(1) 只需要几个辅助指针,算法原地工作。

总结

第一种解法中,为了不使得丢失新链表的头结点,使用一个伪头结点来记录。
并且循环中直接在node.next 创建新节点而不是在node处创建新节点,也是为了防止引用丢失。

第二种解法, 就像评论里面说的,像加了一条辅助线那么巧妙,可以说相当牛皮了。


解法参考至 k神

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值