513. 找树左下角的值
文章链接:代码随想录 (programmercarl.com)
视频链接:怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值_哔哩哔哩_bilibili
笔记
- 层序遍历基本掌握
- 递归:没想到是个深度问题
C++代码
层序遍历
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
int res;
if(root==nullptr)return 0;
que.push(root);
while(!que.empty()){
int size=que.size();
res=que.front()->val;
for(int i=0;i<size;i++){
TreeNode* node=que.front();
que.pop();
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
}
return res;
}
};
递归
class Solution {
public:
int MaxDepth=INT_MIN;
int res;
void findLeft(TreeNode* root,int depth){
if(root->left==nullptr && root->right==nullptr){
if(MaxDepth<depth){
res=root->val;
MaxDepth=depth;
}
}
if(root->left){
findLeft(root->left,depth+1);
}
if(root->right){
findLeft(root->right,depth+1);
}
}
int findBottomLeftValue(TreeNode* root) {
findLeft(root,1);
return res;
}
};
112. 路径总和
文章链接:代码随想录 (programmercarl.com)
视频链接:拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和_哔哩哔哩_bilibili
笔记
- 递归:
- 终止条件:1.不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。2.遇到叶子节点直接返回false
- 中节点没有处理逻辑
-
递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:
-
如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
-
- 迭代
- 用pair来存储路径数值
- 每次入栈的数值都加上了经过的路径上的数
C++代码
递归
class Solution {
private:
bool traversal(TreeNode* cur, int count) {
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回
if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true;
count += cur->left->val; // 回溯,撤销处理结果
}
if (cur->right) { // 右
count -= cur->right->val; // 递归,处理节点;
if (traversal(cur->right, count)) return true;
count += cur->right->val; // 回溯,撤销处理结果
}
return false;
}
public:
bool hasPathSum(TreeNode* root, int sum) {
if (root == NULL) return false;
return traversal(root, sum - root->val);
}
};
迭代
class solution {
public:
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
文章链接:代码随想录 (programmercarl.com)
视频链接:拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和_哔哩哔哩_bilibili
笔记
- 返回值是二维数组,实际上在计算结果的时候需要一维数组的辅助
- 递归大体上跟112一样,但是要注意path也要回溯
C++代码
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void getPath(TreeNode* root,int count){
if(!root->left && !root->right && count==0){
res.push_back(path);
return;
}
if(!root->left && !root->right)return ;
if(root->left){
path.push_back(root->left->val);
getPath(root->left,count-root->left->val);
path.pop_back();
}
if(root->right){
path.push_back(root->right->val);
getPath(root->right,count-root->right->val);
path.pop_back();//回溯
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
res.clear();
path.clear();
if(!root)return res;
path.push_back(root->val);
getPath(root,targetSum-root->val);//-root->val
return res;
}
};
106. 从中序与后序遍历序列构造二叉树
文章链接:代码随想录 (programmercarl.com)
视频链接:坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树_哔哩哔哩_bilibili
笔记
- 通过切割区间返回节点来计算
- 先切割中序再切割后序
- 切割区间左闭右开,全部都要遵循这个规则
- 递归处理左右区间
- 中序后序的数组长度是一致的
C++代码
class Solution {
private:
// 中序区间:[inorderBegin, inorderEnd),后序区间[postorderBegin, postorderEnd)
TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& postorder, int postorderBegin, int postorderEnd) {
if (postorderBegin == postorderEnd) return NULL;
int rootValue = postorder[postorderEnd - 1];
TreeNode* root = new TreeNode(rootValue);
if (postorderEnd - postorderBegin == 1) return root;
int delimiterIndex;
for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue) break;
}
// 切割中序数组
// 左中序区间,左闭右开[leftInorderBegin, leftInorderEnd)
int leftInorderBegin = inorderBegin;
int leftInorderEnd = delimiterIndex;
// 右中序区间,左闭右开[rightInorderBegin, rightInorderEnd)
int rightInorderBegin = delimiterIndex + 1;
int rightInorderEnd = inorderEnd;
// 切割后序数组
// 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
int leftPostorderBegin = postorderBegin;
int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 终止位置是 需要加上 中序区间的大小size
// 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);
int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了
root->left = traversal(inorder, leftInorderBegin, leftInorderEnd, postorder, leftPostorderBegin, leftPostorderEnd);
root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);
return root;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
// 左闭右开的原则
return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());
}
};
105. 从前序与中序遍历序列构造二叉树
笔记
- 新建节点
- 中序去除根结点
- 前序大小与中序相等
C++代码
class Solution {
public:
TreeNode* traversal(vector<int>& preorder,int preBegin,int preEnd,vector<int>& inorder,int inBegin,int inEnd){
if(preBegin==preEnd)return NULL;
int rootValue=preorder[preBegin];
TreeNode* root=new TreeNode(rootValue);//新建树节点
if(preEnd-preBegin==1)return root;
int demIndex;
for(demIndex=inBegin;demIndex<inEnd;demIndex++){
if(inorder[demIndex]==rootValue)break;
}
int leftInorderBegin=inBegin;
int leftInorderEnd=demIndex;
int rightInorderBegin=demIndex+1;//去除root
int rightInorderEnd=inEnd;
// 两个数组大小相等
int leftPreOrderBegin=preBegin+1;
int leftPreOrderEnd=preBegin+demIndex-inBegin+1;
int rightPreOrderBegin=preBegin+(demIndex-inBegin)+1;
int rightPreOrderEnd=preEnd;
root->left=traversal(preorder,leftPreOrderBegin,leftPreOrderEnd,inorder,leftInorderBegin,leftInorderEnd);
root->right=traversal(preorder,rightPreOrderBegin,rightPreOrderEnd,inorder,rightInorderBegin,rightInorderEnd);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(inorder.size()==0 || preorder.size()==0)return NULL;
return traversal(preorder,0,preorder.size(),inorder,0,inorder.size());
}
};