zoukankan      html  css  js  c++  java
  • 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("");
    }
    
  • 相关阅读:
    资源加载相关
    Ubuntu 使用root登陆帐户
    安装zookeeper时,启动成功,可是状态查询未成功
    使用WinSCP远程连接虚拟机
    分布式服务管理框架-Zookeeper客户端zkCli.sh使用详解
    js怎么监听一类标签的点击事件
    js获取select标签选中的值
    学习
    druid
    Linux上非root用户jdk环境变量配置
  • 原文地址:https://www.cnblogs.com/fyusac/p/13259933.html
Copyright © 2011-2022 走看看