310. Minimum Height Trees
输入:包含n个节点的无向图。n:表示从0到n-1,n个节点。edges:int数组,是从一个节点到另外一个节点。但是没有方向。
输出:以哪些节点为根节点,具有最小高度的树,返回这些根节点。
规则:一个树的高度是指从根节点到叶子节点的最远路径。最小高度树,是指所有树中高度最小的树。
分析:当只有一个节点的时候,只要返回节点0就可以。
当有两个节点且相连的时候,哪个节点做根节点,树的高度都相同。
当有3个节点的时候,node1和node3肯定不能为根节点,因为以node2为根,高度是1;而以node1或者node3高度为2。也就是说当有3个或者以上节点的时候,使用叶子节点做根节点的树肯定不符合要求。假设叶子节点nodeA为根是高度最小树,那么nodeA肯定有子节点还有其他节点,否则一棵树不能包含所有节点。那么以nodeA的子节点为根,高度减1,与假设不符合。有了这个结论:使用叶子节点做根节点的树肯定不符合要求。(这个观点的来源)我们就可以使用动态规划的思路来不断解决更小的问题。
例如上图5个节点的图,node4,node5不是根节点,那谁是呢?把node4,node5从图中移除,只剩下node1,node2,node3,3个节点。
在这3个节点的图中,node1,node3肯定不是根节点。将这两个节点从图中移除。就只有node2。也就是说node2是根节点。
在这个问题规模不断变小的过程中,不断去掉叶子节点。而这个操作不影响原有问题的答案。
public List<Integer> findMinHeightTrees(int n, int[][] edges) {Map<Integer,List<Integer>> graph = createGraph(edges,n);int[] inDegrees = new int[n];for(int[] edge : edges){inDegrees[edge[0]]++;inDegrees[edge[1]]++;}List<Integer> result = new ArrayList<Integer>();Queue<Integer> queue = new LinkedList<Integer>();for(int i=0;i<n;i++){if(inDegrees[i]==0){result.add(i);return result;}else if(inDegrees[i]==1){queue.offer(i);}}while(!queue.isEmpty()){result = new ArrayList<Integer>();int size = queue.size();for(int i=0;i<size;i++){int node = queue.poll();result.add(node);for(Integer toNode : graph.get(node)){inDegrees[toNode]--;if(inDegrees[toNode]==1){queue.offer(toNode);}}}}return result;}private Map<Integer,List<Integer>> createGraph(int[][] edges,int n){Map<Integer,List<Integer>> graph = new HashMap<Integer,List<Integer>>();for(int i=0;i<n;i++){graph.put(i,new ArrayList<Integer>());}for(int[] edge : edges){graph.get(edge[0]).add(edge[1]);graph.get(edge[1]).add(edge[0]);}return graph;}
分析2:分别以每个节点作为根节点计算树的高度,在这个过程中比较记录最小高度minHeight。遍历之前的结果,等于minHeight的节点加入到结果集中。
在计算树的高度的过程中,可以使用动态规划的想法。假设已知 A 的所有相邻节点分别为树根的各个子树的树高,那么 A根的树高等于 已知的各个子树树高中的最大值 加一。方程式表达如下,即状态转换方程:
height(A) = max(height(A.next0), height(A.next2),… height(A.nextk)) + 1(来源网址)
在计算过程中需要记录各个子树的高度,避免重复计算。缓存的key值是“当前节点->子节点”。
private Map<String,Integer> cache = new HashMap<String,Integer>();public List<Integer> findMinHeightTrees(int n, int[][] edges) {Map<Integer,List<Integer>> graph = createGraph(edges,n);int[] heights = new int[n];int minHeight = n;for(int i=0;i<n;i++){heights[i] = findHeight(graph,i,-1);minHeight = Math.min(minHeight,heights[i]);}List<Integer> result = new ArrayList<Integer>();for(int i=0;i<n;i++){if(heights[i]==minHeight){result.add(i);}}return result;}private int findHeight(Map<Integer,List<Integer>> graph,int root,int parent){int height = 0;for(Integer toNode : graph.get(root)){if(toNode==parent){continue;}String key = String.valueOf(root)+"->"+toNode;int tmp;if(cache.get(key)!=null){tmp = cache.get(key);}else{tmp = findHeight(graph,toNode,root);cache.put(key,tmp);}height = Math.max(height,tmp);}return height+1;}private Map<Integer,List<Integer>> createGraph(int[][] edges,int n){Map<Integer,List<Integer>> graph = new HashMap<Integer,List<Integer>>();for(int i=0;i<n;i++){graph.put(i,new ArrayList<Integer>());}for(int[] edge : edges){graph.get(edge[0]).add(edge[1]);graph.get(edge[1]).add(edge[0]);}return graph;}
代码
310. Minimum Height Trees相关推荐
- leetcode 310. Minimum Height Trees | 310. 最小高度树(图的邻接矩阵DFS / 拓扑排序)
题目 https://leetcode.com/problems/minimum-height-trees/ 题解 方法1:图的邻接矩阵 DFS(超时) 我一想,这不就是个图嘛,于是随手敲出一个 DF ...
- LeetCode 310. Minimum Height Trees
文章目录 知识点 结果 菜鸡的DFS+记忆化 网友的BFS"剥洋葱" 实现 菜鸡的DFS+记忆化 代码 反思 网友的BFS"剥洋葱" 代码 反思 知识点 图的遍 ...
- 310. Minimum Height Trees 【Medium】 树
题目:给出一个树,求出所有作为根节点时树的高度最小的节点 思路:用剪枝的办法,每次剪掉叶子节点,最终剩下一个或者两个节点时结束. 原理:一个节点的树的高度为该节点到最远的节点的距离,且此最远节点必为叶 ...
- leetcode310. Minimum Height Trees
题目 For an undirected graph with tree characteristics, we can choose any node as the root. The result ...
- 树的最小高度 Minimum Height Trees
2019独角兽企业重金招聘Python工程师标准>>> 问题: For a undirected graph with tree characteristics, we can ch ...
- LeetCode Minimum Height Trees(拓扑排序)
问题:给出一个图,要求确定树的根,使得树的高度最小. 思路:先求出结点的度.然后将度数为1的入队列.在出队列时,将其邻接结点的度数减1,如果度数为1,则放入队列.直接剩余的结点数小于等于2 具体代码参 ...
- Lecture 16 Minimum Spanning Trees
- HDU 6691 Minimum Spanning Trees
题目 题意: 对于一个n个点的图,每对点 u , v u,v u,v间有 p 0 p_0 p0的几率没有边, p 1 p_1 p1的几率有权值为1的边, p 2 p_2 p2-边权 < = ...
- 继续过中等难度.0309
. 8 String to Integer (atoi) 13.9% Medium . 151 Reverse Words in a String 15.7% Mediu ...
最新文章
- Windows 10 install Pycharm 开发环境
- python创建进程的方法_python进程的状态、创建及使用方法详解
- mysql怎么删除唯一索引_mysql删除唯一索引
- 单继承-继承的概念和语法
- oracle unpivot 空值,sql – 处理UNPIVOT中的NULL值
- 【用jQuery来判断浏览器的类型】及【javascript获取用户ip地址】
- JVM——Java内存模型(JMM)
- 【数据结构】4.1图的创建及DFS深度遍历(不完善)
- apache的poi中设置Excel的单元格样式(HSSFCellStyle)和表格(HSSFSheet)
- 中英文对照 —— 图表等的可视化
- [Python] 生成迭代器 iter() 函数
- 页面置换算法(FIFOLRU)
- 【PC微信探秘】用易语言编写一个微信DLL注入器
- php怎么获取图片信息,PHP 获取图片信息exif
- java程序一图片为背景_利用Java处理图片,更换背景
- 【12306刷票必备!!!】12306订票助手----无所不能的谷歌浏览器chrome插件
- isInterrupted() interrupt() interrupted() 方法的简单解释
- openstreetmap-tile-server-ubuntu-16-04
- 【实例】使用 PHPExcel 读取excel 文件
- 史上最全的StarUML使用教程
热门文章
- JSTL之数字、日期格式化fmt:formatNumber/、fmt:formatDate/
- linux下memcache安装
- java mysql show status_Java 能不能执行mysql 中的show master status 命令
- 不同文件类型输出及ContentType表
- ubuntu mysql混合开发_mysql5.7主从同步 ubuntu
- web编程 模块1 html,PYcore python programming笔记C20 Web编程
- postgresql查询mysql库_postgresql 查看数据库,表,索引,表空间以及大小
- .net动态控件的使用(listview ,treeview,tabControl)
- 实现推拉ui样式_这推拉门隔断,我从没见过!直角设计同时划分3大功能区,太牛了...
- spring体系思维导图