day17 二叉树04
110. 平衡二叉树
用递归的话:得到左右子树的高度,判断其是否差为1,否的话,可以直接返回false了,但要怎么中断呢?——Carl用-1来表示不符合的状态,因为返回结果是自然数。很聪明,我咋没想到呢。。。这应该是大一上计导课就可以想到的小trick。
临时检查:递归三要素是什么?
返回值,递归条件,终止情况?
递归函数的参数和返回值、终止条件、单层递归的逻辑 ——Carl
class Solution {
public:
int flag = 0;
// 返回值:树的高度(-1则是终止)
// 结束条件:空节点 或 下面已经不满足平衡二叉树
// 递归逻辑:通过左右子树的高度,判断并返回自己的高度
int getHeight (TreeNode* root) {
if (!root) return 0;
int lh = getHeight(root->left), rh = getHeight(root->right);
if (lh == -1 || rh == -1) return -1;
if (abs(lh - rh) > 1) return -1;
return lh > rh ? (lh + 1) : (rh + 1);
}
bool isBalanced(TreeNode* root) {
if (getHeight(root) == -1) return false;
else return true;
}
};
257. 二叉树的所有路径
思路:
-
不知道到底有多少条路径,要回溯。
-
递归回溯
递归不需要返回值,终止条件是左右孩子都完成,单层递归逻辑是回溯。
从root开始加进数组,有孩子(能递归)就继续,到了叶子结点形成一条路径,然后回溯;
回溯和递归是一一对应的,有一个递归,就要有一个回溯,尽量都在一个括号处理流程里。
class Solution {
private:
vector<string> result;
vector<int> vec;
void print() {
string sPath;
sPath += to_string(vec[0]);
for (int i = 1; i < vec.size(); i++) {
sPath = sPath + "->" + to_string(vec[i]);
}
result.push_back(sPath);
}
void reverse(TreeNode* root) {
if (!root) return;
vec.push_back(root->val);
if (!root->left && !root->right) {
print();
}
reverse(root->left);
reverse(root->right);
vec.pop_back();
}
public:
vector<string> binaryTreePaths(TreeNode* root) {
reverse(root);
return result;
}
};
404. 左叶子之和
首先明确左叶子定义,是叶子结点 && 父节点的左孩子,
用递归试试:
返回值,不用返回,sum全局 / 也可以返回当前节点的所有左叶子之和,参数是结点;
递归终止条件:叶子结点;
单层递归逻辑:有没有左孩子,并是不是左叶子,有没有右孩子
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (!root->left && !root->right) return 0;
int leftSum = 0, rightSum = 0;
if (root->left) {
if (!root->left->left && !root->left->right) leftSum += root->left->val;
else leftSum = sumOfLeftLeaves(root->left);
}
if (root->right) {
rightSum = sumOfLeftLeaves(root->right);
}
return leftSum + rightSum;
}
};
顺便尝试了一下vscode写力扣,还行。
今日小结
做力扣解具体问题也视为一项业务,对业务的理解也很重要;
递归真的很省心,几天没用迭代,估计又忘了。