DFS solution is intuitive. I put my BFS solution below:
class Solution { public: int countNodes(TreeNode* root) { if (!root) return 0; // Case 1: complete int hl = 0, hr = 0; TreeNode *pl = root; while(pl) { hl ++; pl = pl->left; } TreeNode *pr = root; while(pr) { hr ++; pr = pr->right; } if (hl == hr) { return pow(2, hl) - 1; } // Case 2: incomplete deque<TreeNode *> q; q.push_back(root); int pcnt = 1; int level = 0; while(!q.empty()) { auto ptop = q.front(); q.pop_front(); pcnt --; if (ptop->left) q.push_back(ptop->left); if (ptop->right) q.push_back(ptop->right); if(pcnt == 0) { pcnt = q.size(); level ++; if (level == hr) { break; } } } return pow(2, hr) - 1 + pcnt; } };