目录
一、513. 找树左下角的值
题目链接:力扣
文章讲解:代码随想录
视频讲解: 怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值
题目:
给定一个二叉树的 根节点 root
,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*///递归
class Solution {
public:/*
void dfs(TreeNode* root, int depth, int& max_depth, int& ans){
if(!root) return;
if (!root->left && !root->right){
if(depth > max_depth){
max_depth = depth;
ans = root->val;
}
}
dfs(root->left, depth+1, max_depth, ans);
dfs(root->right, depth+1, max_depth, ans);
return;
}
int findBottomLeftValue(TreeNode* root) {
int depth = 0;
int max_depth = -1;
int ans = 0;
dfs(root, depth, max_depth, ans);
return ans;
}*///迭代
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
que.push(root);
int ans = 0;
while(!que.empty()){
TreeNode* node = que.front();
que.pop();
if (node->right) que.push(node->right);
if (node->left) que.push(node->left);
ans = node->val;
}
return ans;
}
};
时间复杂度: O(n) 空间复杂度: O(n)
⏲:8:14
总结:先序遍历,在同一层中,先左后右。在迭代中,使用队列,先进先出,将左子树后入,可使最后留下的即为所求的。
二、112. 路径总和
题目链接:力扣
文章讲解:代码随想录
视频讲解:拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和
题目:给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。 叶子节点 是指没有子节点的节点。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//递归正序
/*bool order(TreeNode* node, int sum, int targetSum)
{
if (!node->left && !node->right)
{
if (sum == targetSum) return true;
else
return false;
}
bool leftbool = false, rightbool = false;
if (node->left) leftbool = order(node->left, sum + node->left->val, targetSum);
if (node->right) rightbool = order(node->right, sum + node->right->val, targetSum);
return leftbool || rightbool;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root) return false;
return order(root, root->val, targetSum);
}*/
//递归倒减
/*bool order(TreeNode* node, int sum)
{
if (!node) return false;
if (!node->left && !node->right && sum == node->val) return true;
return order(node->left, sum - node->val) || order(node->right, sum - node->val);
}*/
bool hasPathSum(TreeNode* root, int targetSum) {
//return order(root, targetSum);
//迭代法,前序遍历
stack<pair<TreeNode*, int>> st;
if (!root) return false;
st.push(pair<TreeNode*, int>(root, root->val));
while (!st.empty())
{
pair<TreeNode*, int> node = st.top();
st.pop();
if (!node.first->left && !node.first->right && node.second == targetSum) return true;
if (node.first->left)
st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
if (node.first->right)
st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
}
return false;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
vector<vector<int>> ans;
void traversal(TreeNode* node, int sum, vector<int> &path)
{
if (!node->left && !node->right)
{
if (sum == 0)
ans.emplace_back(path);
return;
}
if (node->left)
{
path.emplace_back(node->left->val);
traversal(node->left, sum - node->left->val, path);
path.pop_back();
}
if (node->right)
{
path.emplace_back(node->right->val);
traversal(node->right, sum - node->right->val, path);
path.pop_back();
}
return;
}
public:
vector<vector<int>> pathSum(TreeNode* root, int targetsum) {
if (!root) return ans;
vector<int> path;
path.push_back(root->val);
traversal(root, targetsum - root->val, path);
return ans;
}
};
时间复杂度: O(n) 空间复杂度: O(n)
⏲:11:04
总结:1.路径要返回值,可提前结束遍历,全搜索不用返回值,储存在全局变量或传地址数组中。2.路径问题,关键在于判断递归结束条件,其他按正常递归写。3.回溯:本层依旧使用就回溯,不用就不需要。
三、106. 从中序与后序遍历序列构造二叉树
题目链接:力扣
文章讲解:代码随想录
视频讲解:坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树
题目:给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* creat_tree(vector<int>& inorder, int inorder_begin, int inorder_end, vector<int>& postorder, int postorder_begin, int postorder_end) {
if (postorder_begin > postorder_end) return NULL;
int root_value = postorder[postorder_end];
TreeNode* root = new TreeNode(root_value);
if (postorder_end == postorder_begin) return root;
int target = 0;
for(target = inorder_begin; target <= inorder_end; target++)
if (inorder[target] == root_value) break;
root->left = creat_tree(inorder, inorder_begin, target-1, postorder, postorder_begin, postorder_begin+target-inorder_begin-1);
root->right = creat_tree(inorder, target+1, inorder_end, postorder, postorder_begin+target-inorder_begin, postorder_end-1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return creat_tree(inorder, 0, inorder.size()-1, postorder, 0, postorder.size()-1);
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* order(vector<int> &inorder, int inlt, int inrt, vector<int> &postorder, int pslt, int psrt)
{
if (inlt > inrt) return NULL;
TreeNode* node = new TreeNode(postorder[pslt]);
if (inrt-inlt == 0) return node;
int x = 0;
for (int i = inlt; i <= inrt; i++)
if (inorder[i] == postorder[pslt])
{
x = i;
break;
}
node->left = order(inorder, inlt, x-1, postorder, pslt+1, x-inlt+pslt);
node->right = order(inorder, x+1, inrt, postorder, x-inlt+pslt+1, psrt);
return node;
}
TreeNode* buildTree(vector<int>& postorder, vector<int>& inorder) {
return order(inorder, 0, inorder.size()-1, postorder, 0, postorder.size()-1);
}
};
总结:1.构造是通过不同序列的切割逐渐组成的,切割过程中使用索引更加方便且减少时间复杂度。2.切割过程注意循环不变量(习惯左闭右闭)。3.若只有先序和后序不能作出中序,没有中序遍历无法确定左右部分,无法分割。