/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
int getTreeSum(TreeNode* tree) {
}
};
题目提供了数据结构定义,因此只需编写getTreeSum函数即可。
初看题目,按照二叉树必用二分递归的思想,简直是白给的题目.........既然你要求左右子树值必须一致,那么只要求出左右子树的值,取最大值*2,再加上根节点的1,答案不就出来了。因此代码如下:
class Solution {
public:
int getTreeSum(TreeNode* tree) {
int numL,numR,mod=1e9+7;
if(tree==NULL)
return 0;
numL=getTreeSum(tree->left);
numR=getTreeSum(tree->right);
return (max(numL,numR)*2+1)%mod;
}
};
然而只过了11/20的数据点,如果是考试只能拿55分。观察发现,其实一边计算一边取余,无法保证取余的结果仍然是“最大值”。例如L=10,R=5,让L和R都对7求余的结果反而是R>L。上述代码的问题就是左右子树的getTreeSum结果都是求余后的结果,对其比大小并不靠谱。
进一步思考正解,通过草稿纸画图发现,题目要求的左右子树权值和相等也可以理解为“把两个子树”变成一样的树结构。问题实际上是求一颗满二叉树的结点总数(最小权值是正整数1)。
因此题目正解:只需求出二叉树的高度n,根据教材上的二叉树的性质2,满二叉树结点总数为2^n-1。
class Solution {
public:
int getHigh(TreeNode* tree)/**< 求高度 */
{
if(tree==NULL)
return 0;
return max(getHigh(tree->left),getHigh(tree->right))+1;
}
int getTreeSum(TreeNode* tree) {
int n=getHigh(tree),mod=1e9+7,s=1;
for(int i=1;i<=n;i++) /**< 求2^n */
s=s*2%mod;
return (s-1+mod)%mod;
}
};