目录
一、找树左下角的值-LeetCode 513
Leecode链接: leetcode 513
文章链接: 代码随想录
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例:
输入: root = [2,1,3]
输出: 1
思路
递归:题目需要找最左下角的值,那么这个值肯定时叶子节点的值,其次他还得是最左边的,叶子节点利用变量depth递归来计数,每递归一次加1,回退就减1,当遍历到叶子节点时就保存这个值。但要求是最左边的,可以利用depth来判断,当depth首次最大时且该节点是叶子节点时,他一定是最左边的。迭代:每次遍历时,保存队列第一个出队得元素,直到循环推出,最后保存的数一定是最左边的。
实现代码
1.递归
//cpp
class Solution{
public:
int maxdepth = INT32_MIN;
int res;
void dfs(TreeNode* root,int depth){
if(root->left == nullptr && root->right == nullptr){
if(depth > maxdepth){
depth = maxdepth;
res = root->val;
}
return;
}
if(root->left){
depth++;
dfs(root->left,depth);
depth--;
}
if(root->right){
depth++;
dfs(root->right,depth);
depht--;
}
return;
}
int findBottomLeftValue(TreeNode* root) {
dfs(root,1);//这里写1或者0都可以,因为具体多少不重要,只要是最大值就行,写1符合逻辑
return res;
}
2.迭代
//cpp
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
int result = 0;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == 0) result = node->val; // 记录最后一行第一个元素
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
个人问题
递归法没有写出来,深度递归写的不熟练。
总结
整体运用了二叉树深度的求法,以及回溯的思想。
二、路径总和-LeetCode 112
Leecode链接: LeetCode 112
文章链接: 代码随想录
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
示例:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
思路
思路很简单,使用后续遍历+回溯,因为需要不断来回判断状态,当找到符合结果的就返回true,否则返回false。
实现代码
//cpp
class Solution {
public:
bool get(TreeNode* root,int sum,int target){
//sum = sum + root->val;
if(root->left == nullptr && root->right == nullptr){
if(sum == target){
return true;
}
else{
return false;
}
}
if(root->left){
sum += root->left->val;
bool a = get(root->left,sum,target);
if(a) return true;
sum -= root->left->val;
}
if(root->right){
sum += root->right->val;
bool b = get(root->right,sum,target);
if(b) return true;
sum -= root->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
bool res = get(root,root->val,targetSum);
return res;
}
};
leetcode113题
//cpp
class Solution {
public:
vector<vector<int>> res;
void get(TreeNode* root,int target,vector<int>& path){
if(root->left == nullptr && root->right == nullptr && target == 0){
res.push_back(path);
return;
}
if(root->left){
target -= root->left->val;
path.push_back(root->left->val);
get(root->left,target,path);
path.pop_back();
target += root->left->val;
}
if(root->right){
target -= root->right->val;
path.push_back(root->right->val);
get(root->right,target,path);
path.pop_back();
target += root->right->val;
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<int>path;
if(root == nullptr) return res;
path.push_back(root->val);
get(root,targetSum-root->val,path);
return res;
}
};
个人问题
个人使用依次递增来判断是否符合条件,其实可以递减,减到0时必定符合条件,这样可以避免多传递一个参数。
总结
还是回溯加递归,不过函数返回值为bool类型,当不要返回具体路径时,函数返回值一般为bool类型,因为主要判断是否存在这么一条路径,给出是或者否即可。类似于113题需要你给出具体路径时,就不要返回bool,而是返回void,符合条件的路径保存在一个全局变量res中即可。
三.从中序与后序遍历序列构造二叉树-LeeCode 106
Leecode链接: LeetCode 106
文章链接: 代码随想录
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
思路
思路很简单,难的是代码复现。题目切入点为后续遍历数组的末尾元素,该元素一定是中间节点,这是遍历顺序决定的。然后根据该节点在中序遍历中寻找下标,接着以这个下标为分界点,切割中序遍历数组与后序遍历数组,将其分成左右子树数组,最后递归处理即可。
实现代码
//cpp
class Solution {
public:
TreeNode* build(vector<int>& inorder,vector<int>& postorder){
if(postorder.size() == 0) return nullptr;
int postnum = postorder[postorder.size()-1];
TreeNode* root = new TreeNode(postnum);
if(postorder.size() == 1) return root;
int i;
for(i = 0;i<inorder.size();i++){
if(inorder[i] == postnum){
break;
}
}
vector<int>leftorder(inorder.begin(),inorder.begin() + i);
vector<int>rightorder(inorder.begin() + i + 1,inorder.end());
postorder.pop_back();
vector<int>leftpost(postorder.begin(),postorder.begin() + leftorder.size());
vector<int>rightpost(postorder.begin() + leftorder.size(),postorder.end());
root->left = build(leftorder,leftpost);
root->right = build(rightorder,rightpost);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size() == 0) return nullptr;
return build(inorder,postorder);
}
};
leetcode105
///cpp
class Solution {
public:
TreeNode* build(vector<int>& preorder,int preorderbegin,int preorderend,vector<int>& inorder,int inorderbegin,int inorderend){
if(preorderbegin == preorderend) return nullptr;
int num = preorder[preorderbegin];
TreeNode* root = new TreeNode(num);
if(preorderbegin - preorderend == 1){
return root;
}
int i;
for(i = inorderbegin;i<inorderend;i++){
if(inorder[i] == num){
break;
}
}
int leftinorderbegin = inorderbegin;
int leftinorderend = i;
int rightinorderbegin = i + 1;
int rightinorderend = inorderend;
int leftpreorderbegin = preorderbegin + 1;
int leftpreorderend = preorderbegin + 1 + i - inorderbegin;
int rightpreorderbegin = preorderbegin + 1 + i - inorderbegin;
int rightpreorderend = preorderend;
root->left = build(preorder,leftpreorderbegin,leftpreorderend,inorder,leftinorderbegin,leftinorderend);
root->right = build(preorder,rightpreorderbegin,rightpreorderend,inorder,rightinorderbegin,rightinorderend);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(inorder.size() == 0 || preorder.size() == 0) return nullptr;
return build(preorder,0,preorder.size(),inorder,0,inorder.size());
}
};
个人问题
代码没有自己写出来。
总结
题目也可以不用每递归一次创建四个数组,在函数参数处添加数组首尾下标即可。