133. 克隆图

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 133. 克隆图

注意:本题中文版提交的时候有 Bug,只能在英文版解答。本题来自 LeetCode:133. 克隆图[1]

题目描述

Given a reference of a node in a connected undirected graph, return a deep copy (clone) of the graph. Each node in the graph contains a val (int) and a list (List[Node]) of its neighbors.

Example:

133. 克隆图

Input:
{"$id":"1","neighbors":[{"$id":"2","neighbors":[{"$ref":"1"},{"$id":"3","neighbors":[{"$ref":"2"},{"$id":"4","neighbors":[{"$ref":"3"},{"$ref":"1"}],"val":4}],"val":3}],"val":2},{"$ref":"4"}],"val":1}

Explanation:
Node 1's value is 1, and it has two neighbors: Node 2 and 4.
Node 2's value is 2, and it has two neighbors: Node 1 and 3.
Node 3's value is 3, and it has two neighbors: Node 2 and 4.
Node 4's value is 4, and it has two neighbors: Node 1 and 3.

Note:
The number of nodes will be between 1 and 100.
The undirected graph is a simple graph, which means no repeated edges and no self-loops in the graph.
Since the graph is undirected, if node p has node q as neighbor, then node q must have node p as neighbor too.
You must return the copy of the given node as a reference to the cloned graph.

广度优先遍历

题目分析

本题题意就是拷贝图,先采用广度优先遍历解答。可以分成两步:

  • 采用一个映射表,广度遍历生成老节点和新节点的映射关系。
  • 遍历映射表的元素,将新图的每个节点的相邻节点列表设置好。
  • 题目解答

    
    /*
    // Definition for a Node.
    class Node {
        public int val;
        public ListNode neighbors;
    
        public Node(int _val) {
            val = _val;
            neighbors = new ArrayListNode();
        }
    }
    */
    class Solution {
        public Node cloneGraph(Node node) {
            if(node == null) {
                return null;
            }
            // 存储老节点和新节点的映射关系
            MapNode, Node table = new HashMap();
    
            ListNode queue = new LinkedList();
            queue.add(node);
            // 先拷贝个节点
            while(!queue.isEmpty()) {
                Node oldNode = queue.remove(0);
                // 注意:Node实际的构造函数很注释的不一致
                table.put(oldNode, new Node(oldNode.val, new ArrayListNode()));
                for(Node neighbor : oldNode.neighbors) {
                    if(!table.containsKey(neighbor)) {
                        queue.add(neighbor);
                    }
                }
            }
            // 连接相邻节点
            for(Map.EntryNode, Node entry : copyTable.entrySet()) {
                Node oldNode = entry.getKey();
                Node newNode = entry.getValue();
                for(Node neighbor : oldNode.neighbors) {
                    newNode.neighbors.add(table.get(neighbor));
                }
            }
            return table.get(node);
        }
    }
    

    复杂度分析:
    时间复杂度: O(n ^ 2) n个节点可能会相互相邻。
    空间复杂度: O(n),节点最多和其余 n-1个节点相邻,故队列最大长度可能为 n - 1

    深度优先遍历

    题目分析

    先采用深度优先遍历解答。可以分成两步:

  • 采用一个映射表,深度遍历生成老节点和新节点的映射关系。
  • 遍历映射表的元素,将新图的每个节点的相邻节点列表设置好。
  • 题目解答

    
    /*
    // Definition for a Node.
    class Node {
        public int val;
        public ListNode neighbors;
    
        public Node(int _val) {
            val = _val;
            neighbors = new ArrayListNode();
        }
    }
    */
    class Solution {
    
        public void dfs(Node node, MapNode, Node table) {
            if(table.containsKey(node)) {
                return;
            }
            // 注意:Node实际的构造函数和注释的不一致
            table.put(node, new Node(node.val, new ArrayListNode()));
            for(Node neighbor : node.neighbors) {
                if(!table.containsKey(neighbor)) {
                    dfs(neighbor, table);
                }
            }
        }
    
        public Node cloneGraph(Node node) {
            if(node == null) {
                return null;
            }
            // 映射关系
            MapNode, Node table = new HashMap();
            // 深度遍历
            dfs(node, table);
    
            // 连接相邻节点
            for(Map.EntryNode, Node entry : table.entrySet()) {
                Node oldNode = entry.getKey();
                Node newNode = entry.getValue();
                for(Node neighbor : oldNode.neighbors) {
                    newNode.neighbors.add(table.get(neighbor));
                }
            }
            return table.get(node);
        }
    }
    

    复杂度分析:
    时间复杂度: O(n ^ 2) n个节点可能会相互相邻。
    空间复杂度: O(n),节点可能为首尾相连的链表

    优化版深度遍历

    题目分析

    深度遍历可以直接在遍历的时候,就将响铃节点链表设置好。

    题目解答

    
    /*
    // Definition for a Node.
    class Node {
        public int val;
        public ListNode neighbors;
    
        public Node(int _val) {
            val = _val;
            neighbors = new ArrayListNode();
        }
    }
    */
    class Solution {
    
        public Node dfs(Node node, MapNode, Node table) {
            if(table.containsKey(node)) {
                return table.get(node);
            }
            Node newNode = new Node(node.val, new ArrayListNode());
            // 注意:Node实际的构造函数和注释的不一致
            table.put(node, newNode);
            for(Node neighbor : node.neighbors) {
                newNode.neighbors.add(dfs(neighbor, table));
            }
            return newNode;
        }
    
        public Node cloneGraph(Node node) {
            if(node == null) {
                return null;
            }
            // 深度遍历
            return dfs(node, new HashMap());
        }
    }
    

    复杂度分析:
    时间复杂度: O(n ^ 2) n个节点可能会相互相邻。
    空间复杂度: O(n),节点可能为首尾相连的链表

    参考资料

    1. 克隆图: https://leetcode.com/problems/clone-graph/

    原文始发于微信公众号(xiaogan的技术博客):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> 133. 克隆图


      转载请注明: 好好学java 133. 克隆图

     上一篇
    39&40. 组合总和 I & II 39&40. 组合总和 I & II
    回溯法,可先解答: 39. 组合总和本题来自 LeetCode:39. 组合总和[1] 题目描述给定一个无重复元素的数组  candidates  和一个目标数  target ,找出  candidates  中所有可以使数字和为  ta
    2021-04-05
    下一篇 
    138. 复制带随机指针的链表 138. 复制带随机指针的链表
    本题来自 LeetCode:138. 复制带随机指针的链表[1] 题目描述给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的   深拷贝。 我们用一个由 n个节点组成的链表来表示输入
    2021-04-05