二叉树
404 左叶子之和 easy
左叶子结点也好判断,若某结点属于左结点,且无子树,就是左叶子结点
即也如此,所以如果要判断,必然要从父结点下手,涉及到三层结点的处理
如果要使用递归法,要使用后序遍历(左右中),从下往上进行累加,代码如下:
int sumOfLeftLeaves(TreeNode* root) {
if (!root) return 0;
int leftValSum = 0;
if (root->left && !root->left->left && !root->left->right)
leftValSum += root->left->val;
return leftValSum + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
之所以看不出来后序遍历的痕迹,是因为左右中写在一起,做return的结果。
而迭代法,则前中后三种写法皆可,此处以前序遍历为例,代码如下:
int sumOfLeftLeaves(TreeNode* root) {
stack<TreeNode*> stk;
if (root) stk.push(root);
int res = 0;
while (!stk.empty()) {
TreeNode* cur = stk.top();
stk.pop();
if (cur->left && !cur->left->left && !cur->left->right)
res += cur->left->val;
if (cur->left) stk.push(cur->left);
if (cur->right) stk.push(cur->right);
}
return res;
}
利用这道题,顺道回顾一下前序遍历的统一写法,即标记法:
int sumOfLeftLeaves(TreeNode* root) {
stack<TreeNode*> stk;
int res = 0;
if(!root) return res;
stk.push(root);
while (!stk.empty()) {
TreeNode *cur = stk.top();
if (cur) {
stk.pop();
if (cur->right) stk.push(cur->right);
if (cur->left) {
stk.push(cur->left);
if (!cur->left->left && !cur->left->right)
res += cur->left->val;
}
stk.push(cur);
stk.push(nullptr);
}
else {
stk.pop();
cur = stk.top();
stk.pop();
}
}
return res;
}
513 找树左下角的值 medium
树左下角,在这道题中的意思是最底层的最左边结点,因为示例2如下图所示:
所以这道题用层序遍历,会极其方便,因为只需要记录最后一行的第一个结点即可,代码如下:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if (root) que.push(root);
int res = 0;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* cur = que.front();
que.pop();
if (i == 0) res = cur->val;
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return res;
}
这道题也可以用递归法求解,关键在于记录深度,以及如何记录下最后一行的最后一个结点,终止条件就自然是,先满足叶子结点,再判断深度是否为最大深度,如果是,就保存并退出。
int maxDepth = INT_MIN;
int res = 0;
void reversal (TreeNode* cur, int depth) {
if (!cur->left && !cur->right) {
if (depth > maxDepth) {
maxDepth = depth;
res = cur->val;
}
return;
}
if (cur->left) {
reversal(cur->left, depth + 1);
}
if (cur->right) {
reversal(cur->right, depth + 1);
}
return;
}
int findBottomLeftValue(TreeNode* root) {
reversal(root, 0);
return res;
}
112 路径总和 easy
要判断是否存在一条根结点到叶子结点的路径之和,等于目标和
必然要用到深度遍历,且递归更加方便一些,要用到回溯的思想,
对于这道题,返回类型是布尔类型,传入参数必然有结点,路径之和,既然要与目标和比较,不如传入与目标值的差值,直至结果为0就自然等于目标和
终止条件自然是叶子结点与是否等于目标和()
bool reversal(TreeNode* cur, int sub) {
if (!cur->left && !cur->right && sub == 0) return true;
if (!cur->left && !cur->right) return false;
if (cur->left) {
sub -= cur->left->val;
if (reversal(cur->left, sub)) return true;
sub += cur->left->val;
}
if (cur->right) {
sub -= cur->right->val;
if (reversal(cur->right, sub)) return true;
sub += cur->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root) return false;
return reversal(root, targetSum - root->val);
}
精简后的代码如下:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == nullptr) return false;
if (!root->left && !root->right && targetSum == root->val)
return true;
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
使用迭代法,栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和
bool haspathsum(TreeNode* root, int sum) {
if (root == null) return false;
// 此时栈里要放的是pair<节点指针,路径数值>
stack<pair<TreeNode*, int>> st;
st.push(pair<TreeNode*, int>(root, root->val));
while (!st.empty()) {
pair<TreeNode*, int> node = st.top();
st.pop();
// 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
if (!node.first->left && !node.first->right && sum == node.second) return true;
// 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
if (node.first->right) {
st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
}
// 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
if (node.first->left) {
st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
}
}
return false;
}
113 路径总和II medium
这道题就不是找到一条了,而是找出所有,使用递归法也简单,只需要多添一个数组,记录路径上所遇结点值即可,另外也要对该数组进行回溯处理
vector<vector<int>> res;
vector<int> vec;
void recursive(TreeNode *cur, int count) {
if (!cur->left && !cur->right && count == 0) {
res.push_back(vec);
return;
}
if (!cur->left && !cur->right)
return;
if (cur->left) {
vec.push_back(cur->left->val);
count -= cur->left->val;
recursive(cur->left, count);
count += cur->left->val;
vec.pop_back();
}
if (cur->right) {
vec.push_back(cur->right->val);
count -= cur->right->val;
recursive(cur->right, count);
count += cur->right->val;
vec.pop_back();
}
return ;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if (!root) return res;
vec.push_back(root->val);
recursive(root, targetSum - root->val);
return res;
}