力扣算法学习day45-3

本文介绍了LeetCode算法挑战中的一道题目,涉及如何从描述创建二叉树。作者首先分享了初始的解决方案,该方案在寻找根节点时效率较低,具有O(n^2)的时间复杂度。随后,作者逐步优化了代码,通过记录节点入度找到根节点,将时间复杂度降低到O(n)。最后,展示了使用数组模拟HashMap的超级优化版本,进一步提高了效率至12ms。文章强调了在解决算法问题时不断优化的重要性。
摘要由CSDN通过智能技术生成

力扣算法学习day45-3

周赛T3 - 2196-根据描述创建二叉树

题目

image-20220309212559519

image-20220309213039601

image-20220309213115320

image-20220309213143100

代码实现

/**
 * 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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人山人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值