LeetCode 222. Count Complete Tree Nodes

Given the root of a complete binary tree, return the number of the nodes in the tree.

According to Wikipedia, every level, except possibly the last, is completely filled in a complete binary tree, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.

Design an algorithm that runs in less than O(n) time complexity.

Example 1:

Input: root = [1,2,3,4,5,6]
Output: 6

Example 2:

Input: root = []
Output: 0

Example 3:

Input: root = [1]
Output: 1

Constraints:

  • The number of nodes in the tree is in the range [0, 5 * 104].
  • 0 <= Node.val <= 5 * 104
  • The tree is guaranteed to be complete.

It’s too difficult, this question is too difficult! Maybe it’s because I haven’t made a tree for a long time.

First, let’s understand the concept of complete binary tree in this question, that is, all nodes are sorted from left to right. Then let's review the concept of full binary tree, that is, there are nodes on the left and right of each node or no nodes at all.

This question asks us to find how many nodes there are in a complete binary tree. The most brainless method is to go through them all and count how many there are. But here you can use the properties of complete binary tree to optimize the time complexity, refer to: https://leetcode.com/problems/count-complete-tree-nodes/solutions/61958/concise-java-solutions-o-log -n-2/

First we need a helper function to find the height. The height here is defined as -1 if it is empty, and the height of a root tree is 0.

I think what is described in this solution is a bit difficult to understand. It obtains height by constantly moving to the left. The whole logic is to first find the height of the current root, such as h, and then look at the height of root.right. There are only two situations:

1. h - 1: It means that the height of root.left and root.right are the same, then root.left must be a full binary tree with all nodes at leaf level (at this time, the height of root.left is h - 1), then at this time, root The countNode() is the number of nodes on the left (2^h - 1) + the number of nodes on the right (countNode(root.right)) + root (1)

2. h - 2: At this time, the height of root.left must still be h -1, which means that the right side is shorter than the left side, which means that the last node ends on the left, so root.right must be a full binary tree with all nodes at leaf level. (At this time, the height of root.right is h - 2), then the countNode() of root at this time is the number of nodes on the right (2^(h-1) - 1) + the number of nodes on the right (countNode(root. left))+root(1)

Hmm...then replaced Math.pow(2, h) with left shift.

/**
 * 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 {
    public int countNodes(TreeNode root) {
        int h = height(root);
        if (h < 0) {
            return 0;
        }
        // left subtree has same height as right subtree, then left subtree should be full with height h - 1
        if (height(root.right) == h - 1) {
            return (1 << h) + countNodes(root.right);
        } else {
            // left subtree is higher than right subtree, then right subtree should be full with height h - 2
            return (1 << h - 1) + countNodes(root.left);
        }
    }

    private int height(TreeNode root) {
        return root == null ? -1 : 1 + height(root.left);
    }
}

Then I watched a YouTube video in the comment area below, and I felt it was explained more clearly: https://youtu.be/4wPlA_InnGY

The main idea is to calculate the height all the way to the left and the height all the way to the right, and compare whether left_h and right_h are equal. If they are equal, it means that it is a full binary tree with all nodes at leaf level (the height of the whole tree is left_h). If they are not equal, Just perform countNode() on left and right respectively and then +1 as the return value. I feel that this method is simpler and more intuitive.

/**
 * 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 {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = leftHeight(root);
        int right = rightHeight(root);
        if (left == right) {
            return (1 << left + 1) - 1;
        }
        return countNodes(root.left) + countNodes(root.right) + 1;
    }

    private int leftHeight(TreeNode root) {
        return root == null ? -1 : 1 + leftHeight(root.left);
    }

    private int rightHeight(TreeNode root) {
        return root == null ? -1 : 1 + rightHeight(root.right);
    }
}

This solution also provides iterative solutions. If you are tired, I will try it next time.

Guess you like

Origin blog.csdn.net/qq_37333947/article/details/132832793