每日一题 - 剑指 Offer 35. 复杂链表的复制

题目信息

  • 时间: 2019-06-28

  • 题目链接:Leetcode

  • tag: 链表

  • 难易程度:中等

  • 题目描述:

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

示例1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

提示

1.-10000 <= Node.val <= 10000
2.Node.random为null或指向链表中的节点
3.节点数目不超过1000

解题思路

本题难点

本题的意思是复制一个链表并返回,这个链表与一般链表不同的是多了一个 random 指针。

具体思路

这个复制过程可以分成两步:第一步是复制原始链表上的每个节点,并用next指针相连; 第二步是设置每个节点的random指针。

  • 复制节点:将原始链表的任意节点 N复制为新节点N',再把N'连接到 N的后面。即如果原始链表为A->B->C->D 则复制过后为A->A'->B->B'->C->C'->D->D'
  • 建立random连接: 如果原始链表上的节点 N 的random指针指向节点S,则它对应的复制节点N'的random指针指向节点S的复制节点S',也就是当前节点S的下一个节点。
  • 拆分链表:把这个长链表拆分成两个链表,把奇数位置的节点连接起来就是原始链表,把偶数位置的节点连接起来就是复制出来的链表。

代码

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/
class Solution {
    public Node copyRandomList(Node head) {
        if(head == null){
            return null;
        }
        //插入新节点
        Node cur = head;
        while(cur != null){
            Node clone = new Node(cur.val);
            clone.next = cur.next;
            cur.next = clone;
            cur = clone.next;
        }
        //建立random链接
        cur = head;
        while(cur != null){
            Node clone = cur.next;
            if(cur.random != null){
                clone.random = cur.random.next;
            }
            cur = clone.next;
        }
        //拆分
        cur = head;
        Node cloneHead = head.next;
        while(cur.next != null){
            Node next = cur.next;
            cur.next = next.next;
            cur = next;
        }
        return cloneHead;

    }
}

复杂度分析:

  • 时间复杂度 O(N) : 链表长度为N,遍历所需时间。
  • 空间复杂度 O(1) :没有使用额外的空间保存已保存的节点。

其他优秀解答

解题思路

1.创建HashMap
2.复制结点值
3.复制指向(next,random)

代码

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/
class Solution { //HashMap实现
    public Node copyRandomList(Node head) {
        HashMap<Node,Node> map = new HashMap<>(); //创建HashMap集合
        Node cur=head;
        //复制结点值
        while(cur!=null){
            //存储put:<key,value1>
            map.put(cur,new Node(cur.val)); //顺序遍历,存储老结点和新结点(先存储新创建的结点值)
            cur=cur.next;
        }
        //复制结点指向
        cur = head;
        while(cur!=null){
            //得到get:<key>.value2,3
            map.get(cur).next = map.get(cur.next); //新结点next指向同旧结点的next指向
            map.get(cur).random = map.get(cur.random); //新结点random指向同旧结点的random指向
            cur = cur.next;
        }
        //返回复制的链表
        return map.get(head);
    }
}
posted @ 2020-07-01 12:53  小锵同学、  阅读(126)  评论(0编辑  收藏  举报