110.平衡二叉树
这道题用到了求高度的思路,同时可以用一个标志来表示高度差超过1,用后序遍历来完成这道题,递归三步走:
1. 参数: 返回的是树的高度,传入的参数就是节点;
2. 结束条件: 如果节点等于空,则其高度为0;
3. 单层处理逻辑:首先是左右节点,然后再处理中间节点,这里有个设计巧妙的地方,当两个节点的高度已经超过1时候,就没有必要再向上判断了,直接传一个标志,一直传到根节点即可,否则的话计算返回当前节点的高度。
详细代码如下:
class Solution {
public:
int dfs(TreeNode* root)
{
if(root==nullptr) return 0;
int left = dfs(root->left); //左
int right = dfs(root->right); //右
//中
if(left==-1||right==-1) return -1;
if(abs(left-right)>1) return -1;
return 1+max(left,right);
}
bool isBalanced(TreeNode* root) {
//运用后序遍历
if(dfs(root)==-1) return false;
else return true;
}
};
257. 二叉树的所有路径
这道题目中涉及到回溯,因为需要记录所有路径,所以有一个添加元素然后去掉元素的过程,在我的写法中,我把这个回溯的过程隐藏在了递归到下一层时tmp变量的变化中,详细代码如下:
此外在写这道题时我还遇到了语法不熟的问题:
1. 在函数参数中想要改变vector里面的元素时,要使用引用传递,这样函数内部就使用vector的引用,任何修改都会导致vector的变化,然而使用值传递,函数会复制一份副本,在函数内部使用该副本,不会影响原始的vector;
2. 数字转换成字符的库函数是 to_stirng(val)或者itoa(val);
详细代码如下:
class Solution {
public:
void dfs(TreeNode* root, string tmp, vector<string>& res)
{
if(root==nullptr)return;
if(root->left==nullptr&&root->right==nullptr)
{
res.push_back(tmp+to_string(root->val));
return;
}
dfs(root->left,tmp+to_string(root->val)+"->",res);
dfs(root->right,tmp+to_string(root->val)+"->",res);
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if(root==nullptr) return {};
string tmp;
dfs(root,tmp,res);
return res;
}
};
404.左叶子之和
这道题目我自己写出来了,我的思路是要到左叶子的上一层就要进行加操作,否则很难判断,按照我的思路写了代码,但是我在写的时候结束条件没有弄清楚,我用到的是先序遍历,到最后是调试出来的正确结果,没有return值的时候可ac,思路没有完全清晰,我自己写的代码如下:
class Solution {
public:
void dfs(TreeNode* root, int& res)
{
//if(root->left==nullptr) return;
if(root->left!=nullptr&&root->left->left==nullptr&&root->left->right==nullptr)
{
res+=root->left->val;
//return;
}
if(root->left) dfs(root->left,res);
if(root->right) dfs(root->right,res);
}
int sumOfLeftLeaves(TreeNode* root) {
int res=0;
dfs(root,res);
return res;
}
};
学习代码随想录的思想:
递归三部曲:
1. 确定递归函数的参数和返回值
判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int,使用题目中给出的函数就可以了。
2. 确定终止条件
如果遍历到空节点,那么左叶子值一定是0
if (root == NULL) return 0;
注意,只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。 所以如果当前遍历的节点是叶子节点,那其左叶子也必定是0,那么终止条件为:
if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0; //其实这个也可以不写,如果不写不影响结果,但就会让递归多进行了一层。
3. 确定单层递归的逻辑
当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
详细代码如下:
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root==nullptr) return 0;
if(root->left==nullptr&&root->right==nullptr) return 0;
int left = sumOfLeftLeaves(root->left);//左
if(root->left&&root->left->left==nullptr&&root->left->right==nullptr) left=root->left->val;
int right = sumOfLeftLeaves(root->right);//右
return left+right; //中
}
};
通过学习代码随想录的思想,理清了自己的思路,我自己的思路是前序遍历,结束条件是root==nullprt,单层的处理逻辑里,添加元素的部分为中,依次是左右,清晰思路后的代码如下:
class Solution {
public:
void dfs(TreeNode* root, int &res)
{
if(root==nullptr) return;
if(root->left!=nullptr&&root->left->left==nullptr&&root->left->right==nullptr)
//中
{
res+=root->left->val;
}
dfs(root->left, res); //左
dfs(root->right, res); //右
}
int sumOfLeftLeaves(TreeNode* root) {
int res = 0;
dfs(root, res);
return res;
}
};