力扣算法学习day45-3
周赛T3 - 2196-根据描述创建二叉树
题目
代码实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
// 当时想到的方法,第二题做久了,差一点就弄出来了。出来一下就补上了,不过速度较慢,1000ms
// 思路,用的简单思路,让构建二叉树,给了信息,我就先按照给的信息构建好二叉树,然后再找根结点。
// 然后我这里为了找根结点,先遍历了一次O(n^2)时间复杂度的双重遍历,即,找一个父节点不是其他
// 结点的子节点,这个方法实在拖慢了速度。
// public TreeNode createBinaryTree(int[][] descriptions) {
// HashMap<Integer,TreeNode> map = new HashMap<>();
// TreeNode root = null;
// int rootValue = 0;
// boolean flag = true;
// for(int i = 0;i < descriptions.length;i++){
// flag = true;
// rootValue = descriptions[i][0];
// for(int j = 0;j < descriptions.length;j++){
// if(descriptions[j][1] == rootValue){
// flag = false;
// break;
// }
// }
// if(flag){
// break;
// }
// }
// for(int[] temp : descriptions){
// TreeNode person = null;
// TreeNode child = null;
// if(map.containsKey(temp[0])){
// person = map.get(temp[0]);
// } else{
// person = new TreeNode(temp[0]);
// if(temp[0] == rootValue){
// root = person;
// }
// }
// if(map.containsKey(temp[1])){
// child = map.get(temp[1]);
// } else{
// child = new TreeNode(temp[1]);
// }
// if(temp[2] == 1){
// person.left = child;
// } else{
// person.right = child;
// }
// map.put(temp[0],person);
// map.put(temp[1],child);
// }
// // 找根结点
// return root;
// }
// 优化:找根结点不需要那么麻烦,其实直接找入度为0的结点即为父节点了。以下为修改了找根结点后
// 的代码,速度:72ms,加了个10000的其实容量,速度67ms,额,案例都通过了,我看条件感觉有点擦边。
// public TreeNode createBinaryTree(int[][] descriptions) {
// Map<Integer,TreeNode> map = new HashMap<>(10000);
// // 为了找根结点,创建一个记录每个结点入度的哈希表,这里使用HashMap速度会快一点点
// Map<Integer,Integer> mapD = new HashMap<>();
// for(int[] temp : descriptions){
// TreeNode person = null;
// TreeNode child = null;
// if(map.containsKey(temp[0])){
// person = map.get(temp[0]);
// } else{
// person = new TreeNode(temp[0]);
// }
// if(map.containsKey(temp[1])){
// child = map.get(temp[1]);
// } else{
// child = new TreeNode(temp[1]);
// }
// mapD.put(temp[1],1);
// if(temp[2] == 1){
// person.left = child;
// } else{
// person.right = child;
// }
// map.put(temp[0],person);
// map.put(temp[1],child);
// }
// TreeNode root = null;
// for(Map.Entry<Integer,TreeNode> node : map.entrySet()){
// if(!mapD.containsKey(node.getKey())){
// root = node.getValue();
// }
// }
// return root;
// }
// 超级优化:这再提供一个java大佬的超级优化版,速度12ms
// 原理是使用的数组模拟hashmap,因为题目界限比较小,所以速度更快。以下注释是我的理解,其实核心差不多的。
public TreeNode createBinaryTree(int[][] descriptions) {
// list存储结点,相当于HashMap中的value
TreeNode[] list = new TreeNode[100001];
// father用于存储子节点的父节点
int[] father = new int[100001];
for(int[] description : descriptions){
// 父节点值
int parNo = description[0];
// 孩子结点值
int childNo = description[1];
// 左右子节点
int flag = description[2];
// 如果list中父节点为空,即还没有造,就造一个,不会空,就用par指向它
TreeNode par = list[parNo] == null ? list[parNo] = new TreeNode(parNo) : list[parNo];
// 同理
TreeNode child = list[childNo] == null ? list[childNo] = new TreeNode(childNo) : list[childNo];
// 连接子节点
if(flag == 1){
par.left = child;
}else{
par.right = child;
}
//
father[childNo] = parNo;
}
// 遍历查找没有父节点的结点
for(int i = 0 ; i < 100001 ; i++){
if(list[i] != null && father[i] == 0){
return list[i];
}
}
return null;
}
}