2024/5/1 代码随想录算法训练营第21天 | 513.找树左下角的值、112. 路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树
513.找树左下角的值
题目链接 513
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
随想录
第一次提交
直接想到层序遍历,轻松AC
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
if (!root) return -1;
int res = root -> val;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
res = que.front()->val;
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* cur = que.front();
que.pop();
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return res;
}
};
学习题解
递归方法
深度遍历
视频链接
class Solution {
public:
int maxDepth = 0;
int res = -1;
void traversal (TreeNode* node, int depth) {
if (node->left == nullptr && node->right == nullptr && depth > maxDepth) {
maxDepth = depth;
res = node->val;
}
if (node->left) traversal(node->left, depth + 1);//这里隐藏了对depth 的回溯
if (node->right) traversal(node->right, depth + 1);
}
int findBottomLeftValue(TreeNode* root) {
res = root->val;
traversal(root, 0);
return res;
}
};
112. 路径总和
第一次提交
简单迭代
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root) return false;
if (root->left == nullptr && root->right == nullptr && targetSum == root->val) return true;
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
};
学习优秀题解
视频链接
深度遍历回溯方法
多一种终止条件
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root) return false;
if (root->left == nullptr && root->right == nullptr && targetSum == root->val) return true;
//这种情况下也可以剪枝
if (root->left == nullptr && root->right == nullptr && targetSum != root->val) return false;
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
};
113.路径总和ii
题目链接 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
很自然的想到回溯
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void traversal(TreeNode* node, int targetSum) {
if (node == nullptr) return;
if (node->left == nullptr && node->right == nullptr && targetSum == 0) {
res.push_back(path);
return;
}
if (node->left == nullptr && node->right == nullptr && targetSum != 0) {
return;
}
if(node->left) {
path.push_back(node->left->val);
traversal(node->left, targetSum - node->left->val);
path.pop_back();
}
if(node->right){
path.push_back(node->right->val);
traversal(node->right, targetSum - node->right->val);
path.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(!root) return res;
path.push_back(root->val);
traversal(root, targetSum - root->val);
return res;
}
};
随想录
整体思路变化不大
106.从中序与后序遍历序列构造二叉树
题目链接 106 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
第一次提交
直接找规律递归
注意边界条件和特殊情况的判定,[]; [1]
class Solution {
public:
int findNode (vector<int>& inorder, int target) {
for (int i = 0 ; i < inorder.size(); i++) {
if (target == inorder[i]) return i;
}
return -1;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0) return nullptr;
TreeNode* root = new TreeNode();
root->val = postorder[postorder.size() - 1];
if (inorder.size() == 1) return root;
int leftTreeLength = findNode(inorder, root->val);//1
int rightTreeLength = postorder.size() - leftTreeLength - 1;//3
vector<int> leftInorder = vector<int> (inorder.begin(),inorder.begin() + leftTreeLength);//[0,1)
vector<int> leftPostorder = vector<int> (postorder.begin(),postorder.begin() + leftTreeLength);//[0, 1)
vector<int> rightInorder = vector<int> (inorder.begin() + leftTreeLength + 1, inorder.end());//[2,6)
vector<int> rightPostorder = vector<int> (postorder.begin() + leftTreeLength, postorder.begin() + leftTreeLength + rightTreeLength);//[1, 5)
root->left = buildTree(leftInorder,leftPostorder );
root->right = buildTree(rightInorder, rightPostorder);
return root;
}
};
学习优秀题解
这里的经验是创造左闭右开的集合比较好进行计算,用一个例子去验证编号是否正确。
class Solution {
public:
int findNode(vector<int> vec, int start, int end, int target) {
for (int i = start; i < end; i++) {
if (target == vec[i]) return i;
}
return -1;
}
TreeNode* traversal(vector<int>& inorder, vector<int>& postorder, int inorderStart, int InorderEnd, int postorderStart, int postorderEnd) {
if (inorderStart == InorderEnd) return nullptr;
TreeNode* node = new TreeNode(postorder[postorderEnd - 1]);
if (inorderStart +1 == InorderEnd) return node;
int leftTreeEnd = findNode(inorder, inorderStart, InorderEnd, node->val);
node->left = traversal(inorder, postorder, inorderStart, leftTreeEnd, postorderStart, postorderStart +leftTreeEnd - inorderStart);
node->right = traversal(inorder, postorder, leftTreeEnd + 1, InorderEnd, postorderStart +leftTreeEnd - inorderStart, postorderEnd - 1);
return node;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return traversal(inorder,postorder,0, inorder.size(), 0, postorder.size());
}
};
105.从前序与中序遍历序列构造二叉树
递归方法
这里直接写一遍用索引的迭代方式
class Solution {
public:
int findNode(vector<int>& vec, int start, int end, int target) {
for (int i = start; i < end; i++) {
if (vec[i] == target) return i;
}
return -1;
}
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder, int preStart, int preEnd, int inStart, int inEnd) {
if (preStart == preEnd) return nullptr;
TreeNode* node = new TreeNode(preorder[preStart]);//1
if (preEnd == 1 + preStart) return node;
int inorderLeftEnd = findNode(inorder, inStart, inEnd, node->val);//2
cout<< inorderLeftEnd <<endl;
cout<< preStart+1 <<" <<"<< 1+inorderLeftEnd <<" <<"<< inStart <<" <<"<<inorderLeftEnd<<endl;
node->left = traversal(preorder, inorder, preStart+1 , preStart + 1 + inorderLeftEnd - inStart, inStart, inorderLeftEnd);
//[1,3); [0, 2)
node->right = traversal(preorder, inorder, preStart + 1 + inorderLeftEnd - inStart, preEnd, inorderLeftEnd+ 1, inEnd);
//[3,3); [3,3) RETURN NULLPTR
return node;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return traversal(preorder, inorder, 0, preorder.size(), 0, inorder.size());
}
};
迭代方法
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.size() == 0) return nullptr;
TreeNode* root = new TreeNode(preorder[0]);
stack<TreeNode*> stk;
stk.push(root);
int index = 0;
for (int i = 1 ; i< preorder.size(); i++) {
TreeNode* nextNode = new TreeNode(preorder[i]);
TreeNode* curr = stk.top();
if(curr-> val != inorder[index]) {
stk.push(nextNode);
curr-> left = nextNode;
} else {
while (!stk.empty() && stk.top()-> val == inorder[index]) {
curr = stk.top();
index ++;
stk.pop();
}
stk.push(nextNode);
curr -> right = nextNode;
}
}
return root;
}
};