zoukankan      html  css  js  c++  java
  • 从数组形式创建一棵树(用于leetcode测试)

    这段时间时不时地会在leetcode上做些题,最近做到的大部分是与树相关的题。由于是在本地的IDE上码代码,如果每次测试都要到leetcode上来测的话,不仅要选中复制粘贴一遍,而且每次测试还要读一会条,一次两次还好,次数多了还是比较烦。而如果在本地的类内的main()函数里测试的话,每次构建一个树也比较麻烦,而且仅仅更换数值还好,若要更换树的结构,那工程量就有点大了。

    所以在这里准备写一个创建树的函数来解决这个问题,后面做起题来效率也能高一些。

    话不多说,下面先直接放上所用的代码:

    本例中所构建的树的结构
          5
         / 
        4   8
       /   / 
      11  13  4
     /        
    7    2      1
    
    package learning_java;
    
    import LeetCode.TreeNode;
    import java.util.Deque;
    import java.util.LinkedList;
    
    public class ConstructTree {
        public static TreeNode constructTree(Integer[] nums){
            if (nums.length == 0) return new TreeNode(0);
            Deque<TreeNode> nodeQueue = new LinkedList<>();
            // 创建一个根节点
            TreeNode root = new TreeNode(nums[0]);
            nodeQueue.offer(root);
            TreeNode cur;
            // 记录当前行节点的数量(注意不一定是2的幂,而是上一行中非空节点的数量乘2)
            int lineNodeNum = 2;
            // 记录当前行中数字在数组中的开始位置
            int startIndex = 1;
            // 记录数组中剩余的元素的数量
            int restLength = nums.length - 1;
    
            while(restLength > 0) {
                // 只有最后一行可以不满,其余行必须是满的
    //            // 若输入的数组的数量是错误的,直接跳出程序
    //            if (restLength < lineNodeNum) {
    //                System.out.println("Wrong Input!");
    //                return new TreeNode(0);
    //            }
                for (int i = startIndex; i < startIndex + lineNodeNum; i = i + 2) {
                    // 说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root
                    if (i == nums.length) return root;
                    cur = nodeQueue.poll();
                    if (nums[i] != null) {
                        cur.left = new TreeNode(nums[i]);
                        nodeQueue.offer(cur.left);
                    }
                    // 同上,说明已经将nums中的数字用完,此时应停止遍历,并可以直接返回root
                    if (i + 1 == nums.length) return root;
                    if (nums[i + 1] != null) {
                        cur.right = new TreeNode(nums[i + 1]);
                        nodeQueue.offer(cur.right);
                    }
                }
                startIndex += lineNodeNum;
                restLength -= lineNodeNum;
                lineNodeNum = nodeQueue.size() * 2;
            }
    
            return root;
        }
    
        public static void main(String[] args) {
            Integer[] nums = {5,4,8,11,null,13,4,7,2,null,null,null,1};
            TreeNode root = ConstructTree.constructTree(nums);
            System.out.println(root);
        }
    }
    

    使用时,像上面main()方法中一样,只需要调用类内的静态方法constructTree(Integer[] nums),输入的参量为一个整型的数组,数组中的元素是按层次遍历的二叉树的值(若某节点在下一层中的某个儿子或两个儿子为空,则在下一层的这一个或两个位置填null),与Leetcode中树的表示方法相同,即可以直接把Leetcode上的测试用例按它的形式拖过来直接使用。

    简单解释一下所用的方法,核心思想是在每一层,用一个队列nodeQueue来存储该层的所有节点,然后用父节点的数量的两倍来遍历输入的数组(从上一层结束的地方开始),并从队列中取出(位于上一层的)对应的父节点(此时已从队列中删去,因为用的方法为poll()而不是peek()),对于每一个值,创建相应的子节点链接到父节点,并加入到队列中,依次不断循环,直到遍历完整个数组。

    这里一个踩过的坑是,其中因为一部分数值为null,而如果用int基本类型的数组的话,数组内是不能用null的,因此这里用了int的包装类Integer的数组来作为传入的参数的声明。

    最后,让我们测试一下我们的代码,测试用的树与上面一样,测试中我们采用先序遍历来进行输出,查看结果是否正确:

    /*
    
    用于测试的树,与上例中相同
          5
         / 
        4   8
       /   / 
      11  13  4
     /        
    7    2      1
    
     */
    package learning_java.sortTry;
    
    import LeetCode.TreeNode;
    import learning_java.ConstructTree;
    
    public class ConstructTreeTest {
        public void preOrder(TreeNode root) {
            if (root == null) return;
            System.out.print(root.val + " ");
            preOrder(root.left);
            preOrder(root.right);
        }
    
        public static void main(String[] args) {
            Integer[] nums = {5,4,8,11,null,13,4,7,2,null,null,null,1};
            TreeNode root = ConstructTree.constructTree(nums);
            new ConstructTreeTest().preOrder(root);
        }
    }
    

    测试结果:

    5 4 11 7 2 8 13 4 1
    

    可以看到,我们得到了一棵所需要的树。

    更新

    在实际使用中发现,leetcode中所给的case经常并不是标准的个数,最后一行往往是不满的,如

          5
         / 
        4   
    

    这样一棵树,给出的数组中仅有两个数字:[5, 4],即最后一行中的末尾的null会被舍弃,因此,在我们的程序中,应在遍历过程中加入停止条件(更严谨的方式是保存判定错误输入的条件,并仅在树的最后一行的遍历过程中进行停止判定)。

  • 相关阅读:
    js判断各个浏览器
    js中的全局函数
    js正则表达式大全(转)
    js url编码函数
    原生的ajax(json)
    原生js拖拽
    js浏览器兼容
    何为反向代理、正向代理
    dom元素循环绑定事件的技巧
    media 适屏
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744421.html
Copyright © 2011-2022 走看看