leetcode 剑指 Offer 35. 复杂链表的复制

Posted 枫叶艾辰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 剑指 Offer 35. 复杂链表的复制相关的知识,希望对你有一定的参考价值。

package com.example.lettcode.offer;

import java.util.HashMap;
import java.util.Map;

/**
 * @Class CopyRandomList
 * @Description  剑指 Offer 35. 复杂链表的复制
 * 请实现 copyRandomList 函数,复制一个复杂链表。
 * 在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,
 * 还有一个 random 指针指向链表中的任意节点或者 null。
 *
 * 提示:
 * -10000 <= Node.val <= 10000
 * Node.random 为空(null)或指向链表中的节点。
 * @Author
 * @Date 2020/7/6
 **/
public class CopyRandomList {
    static class Node {
        int val;
        Node next;
        Node random;

        public Node(int val) {
            this.val = val;
            this.next = null;
            this.random = null;
        }
    }   
}
/**
 * 解法1: 先逐个设置复制链表每个节点的next指针
 *       再设置每个节点的random指针,复制random指针时,都需要从头结点还是寻找
 */
public static Node copyRandomList(Node head) {
	if (head == null) return head;
	Node p = head;
	Node neHead = new Node(head.val);
	Node q = neHead;
	// 先找到对应的next
	while (p != null) {
		Node node = new Node(p.val);
		q.next = node;
		q = q.next;
		p = p.next;
	}

	p = head;
	q = neHead.next;
	// 再设置复制链表的random指针
	while (p != null) {
		Node tempP = head;
		Node tempQ = neHead.next;
		// random 需要从头开始重新遍历
		while (tempP != p.random && tempP != null) {
			tempP = tempP.next;
			tempQ = tempQ.next;
		}
		q.random = tempQ;
		p = p.next;
		q = q.next;
	}
	return neHead.next;
}
/**
 * 解法2: 利用HashMap,保存每个节点和其对应的复制节点,以便next和random指针可以直接
 */
public static Node copyRandomList(Node head) {
	if (head == null) return head;
	Map<Node, Node> nodeNodeMap = new HashMap<>();
	Node node = head;
	while (node != null) {
		nodeNodeMap.put(node, new Node(node.val));
		node = node.next;
	}
	/* 方式1
	//复制结点指向
	node = head;
	while (node != null) {
		//新结点next指向同旧结点的next指向
		nodeNodeMap.get(node).next = nodeNodeMap.get(node.next);
		//新结点random指向同旧结点的random指向
		nodeNodeMap.get(node).random = nodeNodeMap.get(node.random);
		node = node.next;
	}
	// 返回旧链表head 所对应的复制结点
	return nodeNodeMap.get(head);*/

	// 方式2
	node = head;
	// 注释的这一行新建了一个头结点,导致这个头结点的random是null,
	// 并非是nodeNodeMap 中head节点对应的复制后的头结点
	// Node newHead = new Node(head.val);
	Node newHead = nodeNodeMap.get(head);
	Node cur = newHead;
	while (node != null) {
		cur.next = nodeNodeMap.get(node.next);
		cur.random = nodeNodeMap.get(node.random);
		node = node.next;
		cur = cur.next;
	}
	return newHead;
}
// 测试用例
public static void main(String[] args) {
	Node head = new Node(7);
	Node node11 = new Node(13);
	head.next = node11;
	node11.random = head;
	Node node12 = new Node(11);
	node11.next = node12;
	Node node13 = new Node(10);
	node12.next = node13;
	node13.random = node12;
	Node node14 = new Node(1);
	node13.next = node14;
	node12.random = node14;
	node14.random = head;
	Node copyHead = copyRandomList(head);
	System.out.println("");
}

以上是关于leetcode 剑指 Offer 35. 复杂链表的复制的主要内容,如果未能解决你的问题,请参考以下文章

[LeetCode]剑指 Offer 35. 复杂链表的复制

LeetCode-剑指 Offer 35. 复杂链表的复制-Java

学习笔记LeetCode剑指Offer 35. 复杂链表的复制

学习笔记LeetCode剑指Offer 35. 复杂链表的复制

学习笔记LeetCode剑指Offer 35. 复杂链表的复制

学习笔记LeetCode剑指Offer 35. 复杂链表的复制