代码随想录算法训练营第十八天
一、513.找树左下角的值
该题用迭代法层序遍历比较简单,代码如下:
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
int result;
if(!root) return result;
que.push(root);
while(!que.empty()){
result = que.front()->val;
int size = que.size();
while(size--){
TreeNode* node = que.front();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return result;
}
};
采用递归法,很容易想到采用前序遍历的方式求深度而不是高度,当深度最大的时候,返回节点的值,由于采用的是前序遍历,访问的第一个最大深度的节点一定是最左边的一个。
class Solution {
public:
int result;
int maxDepth = INT_MIN;
void getdepth(TreeNode* node, int depth){
if(node->left == NULL && node->right ==NULL){
if(depth > maxDepth){
maxDepth = depth;
result = node->val;
}
}
if(node->left){
depth++;
getdepth(node->left, depth);
depth--;
}
if(node->right){
depth++;
getdepth(node->right,depth);
depth--;
}
}
int findBottomLeftValue(TreeNode* root) {
getdepth(root, 0);
return result;
}
};
二、路径总和
112.路径总和1
这题首先想到了用哈希表来解决,加了一点时间复杂度,对于返回bool变量的递归还不够熟练。
哈希表代码:
class Solution {
public:
int sum;
void traversal(TreeNode* node, unordered_set<int>& set){
if(node->left == NULL && node->right == NULL){
set.insert(sum);
return ;
}
if(node->left){
sum += node->left->val;
traversal(node->left, set);
sum -= node->left->val;
}
if(node->right){
sum += node->right->val;
traversal(node->right, set);
sum -= node->right->val;
}
}
bool hasPathSum(TreeNode* root, int targetSum) {
unordered_set<int> set;
if(!root) return false;
sum = root->val;
traversal(root, set);
if(set.find(targetSum) != set.end())
return true;
else
return false;
}
};
布尔变量返回值递归代码:
class Solution {
public:
bool traversal(TreeNode* node, int count){
if(node->left == NULL && node->right == NULL && count == 0) return true;
if(node->left == NULL && node->right == NULL) return false;
if(node->left){
count -= node->left->val;
if(traversal(node->left, count)) return true;
count += node->left->val;
}
if(node->right){
count -= node->right->val;
if(traversal(node->right, count)) return true;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
int count = targetSum - root->val;
return traversal(root,count);
}
};
113.路径总和2
class Solution {
public:
vector<int> path;
void traversal(TreeNode* node, vector<vector<int>>& result, int count){
if(node->left == NULL && node->right == NULL && count == 0){
result.push_back(path);
return ;
}
if(node->left){
count -= node->left->val;
path.push_back(node->left->val);
traversal(node->left, result, count);
count += node->left->val;
path.pop_back();
}
if(node->right){
count -= node->right->val;
path.push_back(node->right->val);
traversal(node->right, result, count);
count += node->right->val;
path.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>> result;
if(!root) return result;
path.push_back(root->val);
int count = targetSum - root->val;
traversal(root, result, count);
return result;
}
};
三、106.从中序与后序遍历序列构造二叉树
- 第一步:如果数组大小为零的话,说明是空节点了。
- 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
- 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
- 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
- 第五步:切割后序数组,切成后序左数组和后序右数组
- 第六步:递归处理左区间和右区间
class Solution {
private:
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;
}
// 切割中序遍历数组
vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());
// 切割后序遍历数组
postorder.resize(postorder.size()-1);
vector<int> leftpostorder(postorder.begin(), postorder.begin() + leftInorder.size());
vector<int> rightpostoreder( postorder.begin() + leftInorder.size(), postorder.end());
root->left = traversal(leftInorder, leftpostorder);
root->right = traversal(rightInorder, rightpostoreder);
return root;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
return traversal(inorder, postorder);
}
};
105.从中序与前序遍历序列构造二叉树
class Solution {
private:
TreeNode* traversal(vector<int>& preorder, int preBegin, int preEnd, vector<int>& inorder, int inBegin, int inEnd){
// 处理前序遍历数组为空的情况
if(preEnd - preBegin == 0) return NULL;
// 前序遍历第一个节点就是根节点
int rootValue = preorder[preBegin];
TreeNode* root = new TreeNode(rootValue);
// 处理叶子节点
if(preEnd - preBegin == 1) return root;
// 找到分割点
int delimiterIndex;
for(delimiterIndex = inBegin; delimiterIndex < inEnd; delimiterIndex++){
if(inorder[delimiterIndex] == rootValue) break;
}
// 分割中序数组
int leftInorderBegin = inBegin;
int leftInorderEnd = delimiterIndex;
int rightInorderBegin = leftInorderEnd + 1;
int rightInorderEnd = inEnd;
// 分割前序数组
int leftPreorderBegin = preBegin + 1;
int leftPreorderEnd = leftPreorderBegin + (leftInorderEnd - leftInorderBegin);
int rightPreorderBegin = leftPreorderEnd;
int rightPreorderEnd = preEnd;
root->left = traversal(preorder, leftPreorderBegin, leftPreorderEnd, inorder, leftInorderBegin, leftInorderEnd);
root->right = traversal(preorder, rightPreorderBegin, rightPreorderEnd, inorder, rightInorderBegin, rightInorderEnd);
return root;
}
public:
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());
}
};