代码随想录算法训练营第十八天 | 513. 找树左下角的值、112. 路径总和、106. 从中序与后序遍历序列构造二叉树、105. 从前序与中序遍历序列构造二叉树
513. 找树左下角的值
题目
解法
- 递归:前序遍历
class Solution {
public:
int maxDepth = INT_MIN;
int result;
void traversal(TreeNode* root, int depth) {
// 终止条件
if(root->left == nullptr && root->right == nullptr) {
if(depth > maxDepth) {
maxDepth = depth;
result = root->val;
}
}
//单层递归逻辑
if(root->left) {
depth++;
traversal(root->left, depth);
depth--;//回溯
}
if(root->right) {
depth++;
traversal(root->right, depth);
depth--;//回溯
}
return ;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0);
return result;
}
};
112. 路径总和
题目
解法
1.递归:前序遍历
class Solution {
public:
bool traversal(TreeNode* root, int count) {
//终止条件
if(!root->left && !root->right && count == 0) return true;
if(!root->left && !root->right) return false;
// 单层递归逻辑
if(root->left) {
count -= root->left->val;
if(traversal(root->left, count)) return true;
count += root->left->val; //回溯值
}
if(root->right) {
count -= root->right->val;
if(traversal(root->right, count)) return true;
count += root->right->val; //回溯值
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
return traversal(root, targetSum - root->val);
}
};
106. 从中序与后序遍历序列构造二叉树
题目
解法
- 递归
class Solution {
public:
TreeNode* traversal(vector<int> inorder, vector<int> postorder) {
// 序列为空返回NULL
if(postorder.size() == 0) return nullptr;
TreeNode* root = new TreeNode(postorder[postorder.size()-1]);
if(postorder.size() == 1) return root;
// 找出后序序列最后一个值作为切割点
int fenGe ;
for (fenGe = 0; fenGe < inorder.size(); fenGe++) {
if(inorder[fenGe] == root->val) break;
}
// 分割中序序列
vector<int> leftinorder(inorder.begin(), inorder.begin()+fenGe);
vector<int> rightinorder(inorder.begin()+fenGe+1, inorder.end());// 需要加1,因为原来分割值是小1的
// 以分割的中序序列来分割后序序列
vector<int> leftpostorder(postorder.begin(), postorder.begin()+leftinorder.size());
vector<int> rightpostorder(postorder.begin()+leftinorder.size(), postorder.end()-1);
// 单层递归
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 nullptr;
return traversal(inorder, postorder);
}
};
基础知识补充
vector的建立
在C++中,std::vector是一个动态数组,它可以随时改变大小。以下是几种创建std::vector的常见方法,并带有相应的例子:
1. 默认构造函数
创建一个空的vector:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec; // 创建一个空的int类型的vector
// 输出vector的大小
std::cout << "Size of vector: " << vec.size() << std::endl; // 输出: Size of vector: 0
return 0;
}
2. 带有初始大小的构造函数
创建一个具有特定大小的vector,所有元素都初始化为该类型的默认值:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec(10); // 创建一个大小为10的int类型的vector,所有元素初始化为0
// 输出vector的大小
std::cout << "Size of vector: " << vec.size() << std::endl; // 输出: Size of vector: 10
return 0;
}
3. 带有初始大小和初始值的构造函数
创建一个具有特定大小的vector,并用指定的值初始化所有元素:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec(10, 5); // 创建一个大小为10的int类型的vector,所有元素初始化为5
// 输出vector的大小
std::cout << "Size of vector: " << vec.size() << std::endl; // 输出: Size of vector: 10
return 0;
}
4. 使用列表初始化
使用花括号{}初始化vector:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用列表初始化一个int类型的vector
// 输出vector的大小
std::cout << "Size of vector: " << vec.size() << std::endl; // 输出: Size of vector: 5
return 0;
}
5. 复制另一个vector
可以使用另一个vector来初始化一个新的vector:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2(vec1); // 使用vec1来初始化vec2
// 输出vec2的大小
std::cout << "Size of vec2: " << vec2.size() << std::endl; // 输出: Size of vec2: 5
return 0;
}
6.从别的vector的部分中建立
从另一个std::vector中取部分元素来创建一个新的std::vector,可以使用多种方法。下面是一个例子,演示了如何从一个vector中取出一个子范围来初始化一个新的vector:
cpp
#include <iostream>
#include <vector>
int main() {
// 创建一个原始的vector
std::vector<int> original_vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 定义子范围的起始和结束迭代器
auto start_it = original_vec.begin() + 2; // 从第3个元素开始(索引为2)
auto end_it = original_vec.begin() + 5; // 到第6个元素结束(不包括,索引为5)
// 使用子范围的迭代器来初始化新的vector
std::vector<int> new_vec(start_it, end_it);
// 输出新vector的内容
for (int num : new_vec) {
std::cout << num << " ";
}
std::cout << std::endl; // 输出: 3 4 5
// 输出新vector的大小
std::cout << "Size of new_vec: " << new_vec.size() << std::endl; // 输出: Size of new_vec: 3
return 0;
}
105. 从前序与中序遍历序列构造二叉树
题目
解法
- 递归
class Solution {
public:
TreeNode* traversal(vector<int>& preorder, int preBegin, int preEnd, vector<int>& inorder, int inBegin, int inEnd) {
// 终止条件
if(preBegin == preEnd) return nullptr;
//前序序列第一个值
TreeNode* root = new TreeNode(preorder[preBegin]);
if (preBegin - preEnd == 1) return root;
//中序序列分割
int sgementIdx ;
for(sgementIdx = inBegin; sgementIdx < inEnd; sgementIdx++) {
if(inorder[sgementIdx] == root->val) break;
}
// 中序左侧序列
int leftInBegin = inBegin;
int leftInEnd = sgementIdx;
// 中序右侧序列
int rightInBegin = sgementIdx + 1;
int rightInEnd = inEnd;
//前序序列分割
// 前序左侧序列
int leftPreBegin = preBegin + 1 ;
int leftPreEnd = preBegin + 1 + sgementIdx - inBegin; // preBgein 不是0,需要注意
// 前序右侧序列
int rightPreBegin = leftPreEnd;
int rightPreEnd = preEnd;
//单层递归
root->left = traversal(preorder,leftPreBegin, leftPreEnd, inorder, leftInBegin,leftInEnd);
root->right = traversal(preorder,rightPreBegin, rightPreEnd, inorder, rightInBegin,rightInEnd);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size() == 0 || inorder.size() == 0) return NULL;
return traversal(preorder, 0, preorder.size(), inorder, 0 , inorder.size());
}
};
总结
注意不变量