【剑指offer】35. 复杂链表的复制

195 阅读2分钟

题目描述

在这里插入图片描述

在这里插入图片描述

// 35. 复杂链表的复制

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


// 牛客
// 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下
// 一个节点,另一个特殊指针random指向一个随机节点),请对此链表进
// 行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参
// 数中的节点引用,否则判题程序会直接返回空)

题解

复制结点部分图解:

在这里插入图片描述

random指向图解:

在这里插入图片描述

// 力扣
// 执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:37.5 MB, 在所有 Java 提交中击败了98.32%的用户
/*
// 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);  // 复制cur遍历的原链表结点,记为clone
			clone.next = cur.next;  // clone.next与cur.next一致
			cur.next = clone;  // 然后让cur.next指向clone本身
			cur = clone.next;  // 移动cur到下一个原链表结点
		}
		// 构建random指向
		cur = head;  // 重置cur回head
		while (cur != null) {  // 循环遍历链表
			// 令clone结点为cur的下一个结点(clone结点即为cur的复制结点)
			Node clone = cur.next;  
			if (cur.random != null)  // 如果cur.random不为null
				// 由于cur和clone的关系,clone是cur的下一个结点
				// clone.random即为cur.random的下一个结点
				clone.random = cur.random.next;  
			cur = clone.next;  // cur移动至下一个原链表结点
		}
		// 两个链表拆分
		cur = head;  // 重置cur回head
		Node cloneHead = head.next;  // 设定复制链表的头结点
		while (cur.next != null) {  // 循环遍历,直到cur.next为空
			// 令cur.next为next,到此我们有cur和next(cur.next)双指针
			Node next = cur.next;  
			// 令cur的next直接指向next.next(cur.next.next)
			// 原链表cur越过了cur的复制点,连上了原链表cur的下一个结点
			cur.next = next.next; 
			cur = next;  // cur右移
		}
		return cloneHead;  // 拆分结束,最后返回复制链表头结点
    }
}


// 牛客
// 运行时间:12ms
// 占用内存:9804k
public class Solution {
    public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null)
            return null;
        // 每个结点复制
        RandomListNode cur = pHead;
        while (cur != null) {
            RandomListNode clone = new RandomListNode(cur.label);
            clone.next = cur.next;
            cur.next = clone;
            cur = clone.next;
        }
        // random指向部署
        cur = pHead;
        while (cur != null) {
            RandomListNode clone = cur.next;
            if (cur.random != null)
                clone.random = cur.random.next;
            cur = clone.next;
        }
        // 分离
        cur = pHead;
        RandomListNode cloneHead = pHead.next;
        while (cur.next != null) {
            RandomListNode next = cur.next;
            cur.next = next.next;
            cur = next;
        }
        return cloneHead;
    }
}