513.找树左下角的值
题目链接:513. 找树左下角的值 - 力扣(LeetCode)
文章链接:代码随想录 (programmercarl.com)
视频链接:怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值
这道题我的第一想法是一直递归到最左边的值,但是有个问题,题目限制了条件,不仅要最左边,还需要最底层。所以我们还需要通过一个int变量depth找到最底层的左边的节点。依旧是递归的想法(其实层序遍历这道题更简单)。
首先,确认递归参数和返回值,除了二叉树的根节点root,还需要一个int参数表示深度
void traversal(TreeNode* root, int depth)
接着,确认递归终止条件,很简单,就是一直递归到叶子节点,然后让depth和此时记录的maxdepth作比较,如果maxdepth<depth.就令maxdepth=depth,result=root->val。
if(root->left==NULL&&root->right==NULL)
{
if(depth>maxdepth)
{
maxdepth=depth;
result=root->val;
}
return;
}
最后,确认单层递归逻辑。首先这道题最底层最左边的节点,并不一定是“左孩子”。但是左孩子的优先级依旧比右孩子高,所以我们需要先递归左边,再递归右边。
if(root->left)
{
depth++;
traversal(root->left,depth);
depth--;
}
if(root->right)
{
depth++;
traversal(root->right,depth);
depth--;
}
总代码如下:
class Solution {
public:
int maxdepth=INT_MIN;
int result;
void traversal(TreeNode* root,int depth)
{
if(root->left==NULL&&root->right==NULL)
{
if(depth>maxdepth)
{
maxdepth=depth;
result=root->val;
}
return;
}
if(root->left)//左
{
depth++;
traversal(root->left,depth);//向左递归
depth--;//回溯
}
if(root->right)//右
{
depth++;
traversal(root->right,depth);//向右递归
depth--;//回溯
}
}
int findBottomLeftValue(TreeNode* root) {
traversal(root,1);
return result;
}
};
depth++;
traversal(root->left,depth);
depth--;
这一段代码体现了回溯的过程,我的理解是一层递归结束后,指针就会自动指向它的上一层节点,而depth(深度)不会自己减少,所以需要depth--
这一段代码也可以精简为: traversal(root->left,depth+1) 这样depth本身的值就不会改变。
112. 路径总和
文章链接:代码随想录 (programmercarl.com)
视频链接:拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和
这道题我的第一想法就是通过递归和回溯,将每一个路径的元素之和求出来,放进map里,再从map里查找targetsum,如果有,就return true,否则,return false。方法当然可以做,但是需要构建一个map哈希结构,有些浪费空间,所以,我的第二想法就是每一次递归就减去递归元素,看到叶节点,是否为0.
代码如下:
class Solution {
public:
bool traversal(TreeNode* root,int count)
{
if(root->left==NULL&&root->right==NULL&&count==0) return true;//说明有路径,节点元素和刚好为是targetsum
if(root->left==NULL&&root->right==NULL) return false;
if(root->left){
count-=root->left->val;
if(traversal(root->left,count)) return true;//将true传递
count+=root->left->val;//回溯
}
if(root->right){
count-=root->right->val;
if(traversal(root->right,count)) return true;//将true传递
count+=root->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==NULL) return false;//考虑空节点
return traversal(root,targetSum-root->val);
}
};
这道题和上一题的区别在于需要记录符合的路径,所以需要一个一维数组path存放单个路径,一个二维数组result来存放多个路径。
与 昨天所写的 257. 二叉树的所有路径 有相似之处。代码如下:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void traversal(TreeNode* root,int count)
{
if(root==NULL) return;
if(root->left==NULL&&root->right==NULL&&count==0){
result.push_back(path);
return;
}
if(root->left)
{
path.push_back(root->left->val);
count-=root->left->val;
traversal(root->left,count);
path.pop_back();//回溯
count+=root->left->val;//回溯
}
if(root->right)
{
path.push_back(root->right->val);
count-=root->right->val;
traversal(root->right,count);
path.pop_back();//回溯
count+=root->right->val;//回溯
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
result.clear();
path.clear();
if(root==NULL) return result;
path.push_back(root->val);
traversal(root,targetSum-root->val);// 把根节点放进路径
return result;
}
};
106.从中序与后序遍历序列构造二叉树
题目链接:106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
文章链接:代码随想录 (programmercarl.com)
视频链接:坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树_哔哩哔哩_bilibili
初次通过两个序列构建二叉树,不是很熟练,在这里讲一下关键的思路。
首先我们要通过序列的性质找到切割点,然后将通过切割点将两个序列切割,再用子序列分别进行递归。
而后序列和中序列有什么关系呢?
首先后序列(左右中)的最后一个元素一定是根节点,然后在中序列中找到该元素,该元素的左边及根节点的左孩子,右边及右孩子,而由于“左孩子”“右孩子”也可以作为各自的根节点,继续向下延申,所以递归的思路就出来了。
代码如下:
class Solution {
public:
TreeNode* traversal(vector<int>& inorder,vector<int>& postorder){
if(postorder.size()==0) return NULL;
int rootvalue=postorder[postorder.size()-1];//后序的最后一个就是根节点
TreeNode* root=new TreeNode(rootvalue);
if(postorder.size()==1) return root;
int delimiterindex;//找切割点
for(delimiterindex=0;delimiterindex<inorder.size();delimiterindex++)
{
if(inorder[delimiterindex]==rootvalue) break;
}
vector<int> leftinorder(inorder.begin(),inorder.begin()+delimiterindex);
vector<int> rightinorder(inorder.begin()+delimiterindex+1,inorder.end());
postorder.resize(postorder.size()-1);
vector<int> leftpostorder(postorder.begin(), postorder.begin() + leftinorder.size());
vector<int> rightpostorder(postorder.begin() + leftinorder.size(), postorder.end());
root->left=traversal(leftinorder,leftpostorder);//子序列进行递归
root->right=traversal(rightinorder,rightpostorder);//子序列进行递归
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
return traversal(inorder,postorder);
}
};
从前序与中序遍历序列构造二叉树 其实总体思路也是一样的,需要找到前序和中序之间,元素的关系。
Day18打卡完成,耗时4小时,不同序列构建二叉树花费了大量时间去理解,再接再厉吧。