Boundary update without `+1` / `-1`
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.
Build confidence with an intuition-first walkthrough focused on binary search fundamentals.
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:
[0, 5 * 104].0 <= Node.val <= 5 * 104Problem summary: 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Binary Search · Bit Manipulation · Tree
[1,2,3,4,5,6]
[]
[1]
closest-binary-search-tree-value)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #222: Count Complete Tree Nodes
/**
* 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;
}
return 1 + countNodes(root.left) + countNodes(root.right);
}
}
// Accepted solution for LeetCode #222: Count Complete Tree Nodes
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func countNodes(root *TreeNode) int {
if root == nil {
return 0
}
return 1 + countNodes(root.Left) + countNodes(root.Right)
}
# Accepted solution for LeetCode #222: Count Complete Tree Nodes
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
// Accepted solution for LeetCode #222: Count Complete Tree Nodes
use std::cell::RefCell;
use std::rc::Rc;
impl Solution {
pub fn count_nodes(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
if let Some(node) = root {
let node = node.borrow();
let left = Self::depth(&node.left);
let right = Self::depth(&node.right);
if left == right {
Self::count_nodes(node.right.clone()) + (1 << left)
} else {
Self::count_nodes(node.left.clone()) + (1 << right)
}
} else {
0
}
}
fn depth(root: &Option<Rc<RefCell<TreeNode>>>) -> i32 {
if let Some(node) = root {
Self::depth(&node.borrow().left) + 1
} else {
0
}
}
}
// Accepted solution for LeetCode #222: Count Complete Tree Nodes
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #222: Count Complete Tree Nodes
// /**
// * 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;
// }
// return 1 + countNodes(root.left) + countNodes(root.right);
// }
// }
Use this to step through a reusable interview workflow for this problem.
Check every element from left to right until we find the target or exhaust the array. Each comparison is O(1), and we may visit all n elements, giving O(n). No extra space needed.
Each comparison eliminates half the remaining search space. After k comparisons, the space is n/2ᵏ. We stop when the space is 1, so k = log₂ n. No extra memory needed — just two pointers (lo, hi).
Review these before coding to avoid predictable interview regressions.
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.
Wrong move: Recursive traversal assumes children always exist.
Usually fails on: Leaf nodes throw errors or create wrong depth/path values.
Fix: Handle null/base cases before recursive transitions.