offer 35 复杂链表的赋值

复杂链表的赋值

image.png

题目分析

普通链表的节点定义以下:node

// Definition for a Node.
class Node {
    int val;
    Node next;
    public Node(int val) {
        this.val = val;
        this.next = null;
    }
}

本题链表的节点的定义以下
比普通的链表多了一个randomdom

// Definition for a Node.
class Node {
    int val;
    Node next, random;
    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}

就是在复制链表的时候还要带着random
image.png
这个时普通链表的复制this

class Solution {
    public Node copyRandomList(Node head) {
        Node cur = head;
        Node dum = new Node(0), pre = dum;
        while(cur != null) {
            Node node = new Node(cur.val); // 复制节点 cur
            pre.next = node;               // 新链表的 前驱节点 -> 当前节点
            // pre.random = "???";         // 新链表的 「 前驱节点 -> 当前节点 」 没法肯定
            cur = cur.next;                // 遍历下一节点
            pre = node;                    // 保存当前新节点
        }
        return dum.next;
    }
}

利用哈希表查表

HashMap 的键值对,构建原来的链表节点和新链表的对应节点的键值对映射关系,而后再遍历next和random引用指向spa

image.png

拼接 + 拆分

image.png
也就是构建新的链表为
node1→node1new→node2→node2 new→⋯
所以当node1指向node2的时候node1new也指向node2new,node1的random指向本身的random的时候,那node1new的random也就只想node1.random.nextcode

/*
// 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 temp = new Node(cur.val);
            //新链表节点的next是当前节点的next
            temp.next = cur.next;
            //当前节点的next是新节点
            cur.next  = temp;
            //继续便利,下一个节点应该是当前节点的next的next,也就是temp的next
            cur = temp.next;
        }
        //对新拼接的链表设置random指向
        cur = head;
        while(cur!=null){
            if(cur.random!=null){
                //下一个节点也就是新节点的随机等于当前旧节点的随机的next
                cur.next.random = cur.random.next;
            }
            cur = cur.next.next;
        }
        //指向完毕 对链表进行拆分 直接拿头节点的next就是新链表的头节点
        cur = head.next;
        Node res = head.next;
        Node pre = head;
        while(cur.next!=null){
            pre.next = pre.next.next;
            cur.next = cur.next.next;
            pre = pre.next;//旧链表
            cur = cur.next;//新链表
        }
        //执行完毕以后,旧链表还差一个尾节点的next的null没加 
        //由于他原本的next应该是新链表,可是拆开以后就变成null了
        pre.next = null;
        return res;
    }
}
相关文章
相关标签/搜索