题目:513.找树左下角的值
自己写出来了!!!!!还是带回溯!!!!!牛!!!!
class Solution {
public:
int depth = 0;
int maxdepth = INT_MIN;
int result;
int findBottomLeftValue(TreeNode* root) {
depth++; //每递归一层,深度加1
if(root->left == NULL && root->right == NULL){
if(depth > maxdepth){
maxdepth = depth;
return root->val;
}
}
if(root->left){
result = findBottomLeftValue(root->left);
depth--; //每返回一层,回溯一次,深度减1
}
if(root->right){
result = findBottomLeftValue(root->right);
depth--;
}
return result; //不管更没更新,都是目前的最左下角的值,直接返回。
}
};
题目:112.路经总和(需要重做)
整体思路比较简单,代码细节上需要注意
1.累减代替累加
2.终止条件:遇到叶子节点就进行判断是否符合条件
3.与终止条件对应:终止条件判断的是当前节点是否为叶子节点,那么在上一层递归时一定要判断node->left和node->right,才不会出现空指针异常的错误
class Solution {
public:
bool traversal(TreeNode *cur, int count){
if(!cur->left && !cur->right && count == 0) return true;
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;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == NULL) return false;
return traversal(root, targetSum - root->val);
}
};
题目:113.路径总和||
思路:设置vec记录每一条路径,result来存放满足条件的路径。每一次递归和回溯在vec里体现。
终止条件:遍历到叶子节点且count累减到0,则这条路径满足条件。
若仅是叶子节点但count不为零,则直接return
单层处理:若不满足终止条件,则进入单层循环。
前序遍历:若node->left不为空,则累加并将node->val存入路径,进入递归。递归结束后,回溯到初始状态。
class Solution {
public:
vector<vector<int>> result;
vector<int> vec; //设置vec和result为外部变量,函数不需要返回参数
void traversal(TreeNode *node, int count){ //终止条件的写法要注意
if(node->left == NULL && node->right == NULL && count == 0) result.push_back(vec);
if(node->left == NULL && node->right == NULL) return;
if(node->left){ //因为要保证递归时不会空指针异常,这里需要判断左子树不为空
count -= node->left->val;
vec.push_back(node->left->val);
traversal(node->left, count);
vec.pop_back();
count += node->left->val;
}
if(node->right){
count -= node->right->val;
vec.push_back(node->right->val);
traversal(node->right, count);
vec.pop_back();
count += node->right->val;
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root == NULL) return result;
vec.push_back(root->val);
traversal(root, targetSum - root->val);
return result;
}
};
题目:106.从中序与后序遍历序列构造二叉树(有难度,需要重做,反复做)
思路:怎样找中间节点?看后序遍历的数列,最后一个数字就是中间节点的值。
怎样找左子树和右子树?用刚刚找的中间节点的值去切割中序遍历到的数列,就可得到左子树和右子树。
然后在后序遍历的数列进行同样切割,分成左右子树。再分别在左右子树中看最后一个数字,又为中间节点。
这样两个数列反复相互切割,构造出新数列。
步骤:
1.后序数组为0,空节点。
2.后序数组最后一个元素为节点元素
3.寻找终须数组位置作为切割点
4.切中序数组
5.切后序数组
6.递归处理左区间和右区间
返回值:要返回根据中序和后序数组构造完的二叉树的根节点,故类型为TreeNode *。
终止条件:如果后序数组为0,即size等于0,则return NULL。
单层递归逻辑
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;
}
//切割中序数组
//左闭右开区间:[0, delimiterIndex)
vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
//[delomiterIndex + 1, end)
vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());
//postorder舍弃末尾元素
postorder.resize(postorder.size() - 1);
//切割后序数组
//依然左闭右开,注意这里使用了左中序数组大小作为切割点
//[0, leftInorder.size)
vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
//[leftInorder.size(), end)
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);
}
};
题目:105.从前序与中序遍历序列构造二叉树
类比着上道题打
class Solution {
public:
TreeNode* traversal(vector<int>& inorder, vector<int>& preorder){
if(preorder.size() == 0) return NULL;
int rootValue = preorder[0];
TreeNode *root = new TreeNode(rootValue);
if(preorder.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());
//切割前
vector<int> leftPreorder(preorder.begin() + 1, preorder.begin() + 1 + leftInorder.size());
vector<int> rightPreorder(preorder.begin() + 1 + leftInorder.size(), preorder.end());
root->left = traversal(leftInorder, leftPreorder);
root->right = traversal(rightInorder, rightPreorder);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(inorder.size() == 0 || preorder.size() == 0) return NULL;
//左闭右开原则
return traversal(inorder, preorder);
}
};