C++中static关键字的正确用法及BST求和问题解析
C++ static关键字正确用法解析(附BST求和问题修复)
问题场景
你用局部static变量实现二叉搜索树(BST)范围内节点值求和时,第一个测试用例(root = [10,5,15,3,7,null,18], low=7, high=15)得到正确结果32,但第二个测试用例(root = [10,5,15,3,7,13,18,1,null,6], low=6, high=10)预期23却得到55,换成类成员变量后结果正常。
错误原因
你代码里的局部static变量sum,只会在第一次进入函数时初始化一次,之后所有函数调用(包括不同测试用例)都会保留之前的数值。第一个测试用例结束后sum是32,第二个测试用例运行时,sum从32开始累加,最终32+23=55,这就是错误的根源。
C++ static关键字的不同场景用法
1. 函数内的局部静态变量
- 生命周期:从第一次初始化开始,直到程序结束
- 作用域:仅限当前函数内部
- 特性:值会在多次函数调用之间保留,适合需要跨调用维持状态的场景(比如统计函数被调用的次数)
- 坑点:不能用于每次调用都需要重置状态的场景,比如你的BST求和,每个测试用例都需要全新的累加起点。
2. 类成员静态变量
- 归属:属于整个类,而非某个对象,所有类实例共享同一个变量
- 初始化:必须在类外部单独初始化(const static整型除外)
- 特性:适合存储类级别的共享数据(比如统计类的实例数量)
- 你的正确代码里,每次测试用例会创建新的
Solution对象,成员变量sum会重新初始化,所以不会有状态残留问题。
修复方案
方案1:无状态递归实现(推荐)
不需要依赖任何外部状态,直接通过递归返回值累加,代码更简洁健壮:
class Solution { public: int rangeSumBST(TreeNode* root, int low, int high) { if (!root) return 0; // 当前节点符合条件就加值,否则加0 int current = (root->val >= low && root->val <= high) ? root->val : 0; // 递归累加左右子树的结果 return current + rangeSumBST(root->left, low, high) + rangeSumBST(root->right, low, high); } };
方案2:保留类成员变量的实现
你的原有正确代码可以继续使用,但要注意这种方式依赖对象状态,不如无状态递归灵活:
class Solution { public: int sum = 0; int rangeSumBST(TreeNode* root, int low, int high) { if (!root) return sum; if (root->val >= low && root->val <= high) sum += root->val; if (root->left) rangeSumBST(root->left, low, high); if (root->right) rangeSumBST(root->right, low, high); return sum; } };
方案3:强制重置static变量(不推荐)
如果一定要用static,需要在每次新的测试用例调用时重置sum,但这种方式存在线程安全问题,代码也不优雅:
class Solution { public: int rangeSumBST(TreeNode* root, int low, int high) { static int sum = 0; // 仅在递归入口(根节点)时重置sum if (root && !root->left && !root->right) { // 这里的判断逻辑仅作示例,实际需根据场景调整 sum = 0; } if (!root) return sum; if (root->val >= low && root->val <= high) sum += root->val; if (root->left) rangeSumBST(root->left, low, high); if (root->right) rangeSumBST(root->right, low, high); return sum; } };
总结
- 局部static变量适合跨函数调用保留状态的场景,绝对不能用于每次调用都需要干净初始值的场景。
- 优先选择无状态的递归实现,避免状态残留带来的隐蔽bug。
内容的提问来源于stack exchange,提问作者Syed Abdulla
相关产品推荐
相关产品推荐

