二叉树
513. 找树左下角的值
题目描述
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
思路
层序遍历,遍历每一层,最左侧数值更新 res。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//迭代法:队列
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
int res;
while (!que.empty())
{
int size = que.size();
for (int i = 0; i < size; i++)
{
TreeNode* node = que.front();
que.pop();
if (i == 0) res = node->val;
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return res;
}
};
112. 路径总和
题目描述
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
思路
递归 & 回溯:
1、参数与返回值
参数:节点、表示路径总和的 int 型变量
返回值:bool类型,true or false
2、终止条件
(1)到达叶子节点且满足路径总和 --> true
(2)到达叶子节点但不满足路径总和 --> false
3、单层的操作
路径:已经走过的节点之和
选择列表:非空左子树、非空右子树
注意:下一层返回上层时,(path 相关的)count 需要回溯
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool traverse(TreeNode* node, int count)
{
//触发终止条件
if (!node->left && !node->right && count == 0) return true;
if (!node->left && !node->right) return false;
//左右子树
if (node->left)
{
count -= node->left->val;
if(traverse(node->left, count)) return true;
count += node->left->val;
}
if (node->right)
{
count -= node->right->val;
if(traverse(node->right, count)) return true;
count += node->right->val;
}
return false;
}
//回溯
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
return traverse(root, targetSum - root->val);
}
};
113. 路径总和 II
题目描述
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
思路
递归 & 回溯:
1、参数与返回值
参数:节点、表示路径总和的 int 型变量
返回值:void类型,需要遍历整个二叉树
2、终止条件
(1)到达叶子节点且满足路径总和,path 对 res 更新;
(2)到达叶子节点但不满足路径总和,只 return;
3、单层的操作
路径:已经走过的节点之和、已经走过的节点的记录
选择列表:非空左子树、非空右子树
注意:下一层返回上层时,count 需要回溯、记录路径的 path 也要回溯。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void traverse(TreeNode* node, int count)
{
//触发结束条件
if (!node->left && !node->right && count == 0)
{
res.push_back(path);
return;
}
if (!node->left && !node->right) return;
if (node->left)
{
path.push_back(node->left->val);
count -= node->left->val;
traverse(node->left,count);
count += node->left->val;
path.pop_back();
}
if (node->right)
{
path.push_back(node->right->val);
count -= node->right->val;
traverse(node->right, count);
count += node->right->val;
path.pop_back();
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
res.clear();
path.clear();
if (root == NULL) return res;
//if (root != NULL)
path.push_back(root->val);
traverse(root, targetSum - root->val);
return res;
}
};
105. 从前序与中序遍历序列构造二叉树
题目描述
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
思路
由先序确定根节点,在中序找到相应位置,划分左右子树,递归构造左右子树,完成二叉树的构造。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//<key,value> key:数值 value:下标
unordered_map<int,int> valToIndex;
TreeNode* build(vector<int>& preorder, int preStart, int preEnd, vector<int>& inorder, int inStart, int inEnd)
{
if (preStart > preEnd)
return NULL;
//从前序确定 “根节点”
int rootVal = preorder[preStart];
//找到 “根节点” 在中序的下标,以划分左右子树
int index = valToIndex[rootVal];
int leftSize = index - inStart;
//树的构造:根节点
TreeNode* root = new TreeNode(rootVal);
//树的构造:左子树
root->left = build(preorder, preStart+1, preStart+leftSize, inorder, inStart, index-1);
//树的构造:右子树
root->right = build(preorder,preStart+leftSize+1,preEnd,inorder,index+1,inEnd);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0; i < inorder.size(); i++)
{
valToIndex[inorder[i]] = i;
}
return build(preorder, 0, preorder.size()-1, inorder, 0, inorder.size()-1);
}
};
106. 从中序与后序遍历序列构造二叉树
题目描述
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
思路
由后序确定根节点,在中序找到相应位置,划分左右子树,递归构造左右子树,完成二叉树的构造。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//<key, value> key:元素值 value:下标
unordered_map<int,int> valToIndex;
TreeNode* build(vector<int>& inorder, int inStart, int inEnd, vector<int>& postorder, int postStart, int postEnd)
{
if (postStart > postEnd)
{
return nullptr;
}
//根据后序确定 “根节点”
int rootVal = postorder[postEnd];
//找到 “根节点” 在中序的下标
int index = valToIndex[rootVal];
//划定左子树范围,含有几个节点
int leftSize = index - inStart;
//树的构造:根节点
TreeNode* root = new TreeNode(rootVal);
//树的构造:左子树
root->left = build(inorder, inStart, index - 1, postorder, postStart, postStart + leftSize - 1);
//树的构造:右子树
root->right = build(inorder, index + 1, inEnd, postorder, postStart + leftSize, postEnd - 1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
for(int i = 0; i < postorder.size(); i++)
{
valToIndex[inorder[i]]=i;
}
return build(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
}
};