zoukankan      html  css  js  c++  java
  • 250. Count Univalue Subtrees

    题目:

    Given a binary tree, count the number of uni-value subtrees.

    A Uni-value subtree means all nodes of the subtree have the same value.

    For example:
    Given binary tree,

                  5
                 / 
                1   5
               /    
              5   5   5
    

    return 4.

    链接: http://leetcode.com/problems/count-univalue-subtrees/

    题解:

    求Uni-value subtree的个数。对树来说这求count的首先思路就是递归了,不过这里要另外构造一个辅助函数来判断root为顶点的subtree是否是Uni-value subtree,假如是Uni-value的subtree,则结果可以+1,否则,我们返回递归求出的左子树的count和右节点的count。假如是Python的话可以一边计算一边返回。Java写起来可能稍微麻烦点。

    Time Complexity - O(n), Space Complexity - O(n).

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public int countUnivalSubtrees(TreeNode root) {
            if(root == null)
                return 0;
            if(root.left == null && root.right == null)
                return 1;
            if(root.left == null) {
                if(isUniValueSubtree(root))
                    return countUnivalSubtrees(root.right) + 1;
                else
                    return countUnivalSubtrees(root.right);
            } else if (root.right == null) {
                if(isUniValueSubtree(root))
                    return countUnivalSubtrees(root.left) + 1;
                else
                    return countUnivalSubtrees(root.left);
            } else {
                if(isUniValueSubtree(root))
                    return countUnivalSubtrees(root.left) + countUnivalSubtrees(root.right) + 1;
                else
                    return countUnivalSubtrees(root.left) + countUnivalSubtrees(root.right);
            }
        }
        
        private boolean isUniValueSubtree(TreeNode root) {
            if(root == null)
                return true;
            if(root.left == null && root.right == null)
                return true;
            else if (root.left != null && root.right != null) {
                if(root.val == root.left.val && root.val == root.right.val)
                    return isUniValueSubtree(root.left) && isUniValueSubtree(root.right);
                else
                    return false;
            } else if (root.left == null) {
                if(root.right.val == root.val)
                    return isUniValueSubtree(root.right);
                else
                    return false;
            } else {
                if(root.left.val == root.val)
                    return isUniValueSubtree(root.left);
                else
                    return false;
            }
        }
    }

    Update: 优化一下

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public int countUnivalSubtrees(TreeNode root) {
            if(root == null)
                return 0;
            if(root.left == null && root.right == null)
                return 1;
            int res = countUnivalSubtrees(root.left) + countUnivalSubtrees(root.right) ;
            return isUniValueSubtree(root) ? res + 1 : res;
        }
        
        private boolean isUniValueSubtree(TreeNode root) {
            if(root == null)
                return true;
            if(root.left == null && root.right == null)
                return true;
            if(isUniValueSubtree(root.left) && isUniValueSubtree(root.right)) {
                if(root.left != null && root.right != null)
                    return (root.left.val == root.right.val) && (root.left.val == root.val);
                else if(root.left != null)
                    return root.left.val == root.val;
                else
                    return root.right.val == root.val;
            }   
            return false;
        }
    }

    Update: 再优化一下。注意判断两个子树是否都为Uni-value subtree的时候用了 '&',这样才能判断两个条件,否则第一个条件为false时就不判断第二个了。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        private int count = 0;
        public int countUnivalSubtrees(TreeNode root) {
            if(root == null)
                return 0;
            isUniValueSubtree(root);
            return count;
        }
        
        private boolean isUniValueSubtree(TreeNode root) {
            if(root == null)
                return true;
           
            if(isUniValueSubtree(root.left) & isUniValueSubtree(root.right)) {
                if(root.left != null && root.left.val != root.val)
                    return false;
                if(root.right != null && root.right.val != root.val)
                    return false;
                count++;
                return true;
            }   
            return false;
        }
    }

    题外话:

    这道题题号是250,马克一下。

    二刷:

    一刷写得比较250,现在要尝试不那么250。要做这道题我们首先要看清楚例子,以及弄明白什么是subtree。 subtree就是指,在一个tree里的某一个node,以及这个node的所有descendants.那么从题目给的例子里,我们复合条件的subtree有4个, 左边第三层里的两个"5"算其2, 右边第二层的"5 - 5",以及第三层的"5"也都算符合条件的subtree,所以我们返回4。 要注意root节点及右边第二层和第三层一起组成的"5-5-5"并不是subtree,这只能算一条root-to-leaf path。另外我们再看一个例子[1, 2, 3],这里作为leaf节点的2和3也分别都是符合条件的subtree,我们返回2。其实所有的leaf节点都是符合条件的。所以我们这道题的处理方法和https://leetcode.com/problems/balanced-binary-tree/ 有点像,都是自底向上进行判断。

    1. 这里我们先创建一个Global变量count, 也可以不用global变量而使用一个size为数组作为参数传递进辅助函数isUnival中。
    2. isUnival主要就是递归地自底向上判断tree是否为unival,也就是所有节点值均相等。有下面几种情况需要考虑
      1. root = null,这时候我们返回true。递归终止时,每个leaf节点都为true,所以null情况我们返回true
      2. 当左子树为unival并且右子树也为unival的时候
        1. 假如左右子节点都为空,则我们遇到leaf节点,合理,count++
        2. 假如左子节点或者右子节点不为空,但值又不与root的值相等时,root本身加左右子树形成的这个subtree不满足题意,我们返回false
        3. 否则,root及其descendants形成一个满足题意的subtree,我们把count++,记录下这个subtree
      3. 要注意判断左右子树是否为unival的时候,左子树和右子树都要判断,这里我们使用了一个'&'符号来避免短路条件判断。也可以分开写。

    Java:

    Time Complexity - O(n), Space Complexity - O(n).

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        int count = 0;
        
        public int countUnivalSubtrees(TreeNode root) {
            if (root == null) return 0;
            isUnival(root);
            return count;
        }
        
        private boolean isUnival(TreeNode root) {
            if (root == null) return true;
            if (isUnival(root.left) & isUnival(root.right)) {
                if (root.left != null && root.left.val != root.val) return false;
                if (root.right != null && root.right.val != root.val) return false;
                count++;
                return true;
            }
            return false;
        }
    }

    Reference:

    https://leetcode.com/discuss/66805/my-java-solution-using-a-boolean-helper-function

    https://leetcode.com/discuss/68057/very-easy-java-solution-post-order-recursion

    https://leetcode.com/discuss/63286/7-line-accepted-code-in-java

    https://leetcode.com/discuss/52210/c-one-pass-recursive-solution

    https://leetcode.com/discuss/50241/recursive-java-solution-with-explanation

    https://leetcode.com/discuss/50357/my-concise-java-solution

    https://leetcode.com/discuss/50420/java-11-lines-added

    https://leetcode.com/discuss/68057/very-easy-java-solution-post-order-recursion

    https://github.com/google/google-java-format

    https://leetcode.com/discuss/55213/my-ac-java-code

    https://leetcode.com/discuss/53431/java-solution-with-dfs

    https://leetcode.com/discuss/50452/ac-clean-java-solution

    https://en.wikipedia.org/wiki/Tree_(data_structure) 

    https://leetcode.com/problems/balanced-binary-tree/

  • 相关阅读:
    网络安全课 06 【Euler、Fermat定理、Miller-Rabin 概率算法】
    网络安全课 05 【保密通信、秘钥分发】
    网络安全课 04 【双重、三重DES】
    状压DP【蓝桥杯 2019_C++_A T9】
    蓝桥杯 2019 C++ A 题解
    凯撒加密【加密+暴力破解+文本单词匹配】
    蓝桥杯 2018 C++ A 题解 【除7、10】
    rest_framework 分页三种
    rest_framework 序列化篇
    rest_framework 解析器(下 全局配置使用)
  • 原文地址:https://www.cnblogs.com/yrbbest/p/5011791.html
Copyright © 2011-2022 走看看