LeetCode513 找树左下角的值
题目链接:找树左下角的值
思路
比较容易想到使用层序遍历,找到最后一层第一个节点即可。
代码
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
int result = 0;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == 0) result = node->val; // 记录最后一行第一个元素
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
Leetcode112 路径总和
题目链接:路径总和
思路
该题找到一个符合条件的路径即可,所以需要bool返回值,终止条件:让计数器
count
初始为目标和,然后每次减去遍历路径节点上的数值。 如果最后count == 0
,同时到了叶子节点的话,说明找到了目标和。 如果遍历到了叶子节点,count
不为
0
,就是没找到。
代码
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if (!root)
return false;
if (!root->left && !root->right && sum == root->val) {
return true;
}
return hasPathSum(root->left, sum - root->val) ||
hasPathSum(root->right, sum - root->val);
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(height)
Leetcode113 路径总和II
题目链接:路径总和 II
思路
本题需要遍历整个树,所以递归函数不需要返回值。
代码
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void traversal(TreeNode* cur, int count) {
if (!cur->left && !cur->right &&
count == 0) { // 遇到了叶⼦节点且找到了和为sum的路径
result.push_back(path);
return;
}
if (!cur->left && !cur->right)
return; // 遇到叶⼦节点⽽没有找到合适的边,直接返回
if (cur->left) { // 左 (空节点不遍历)
path.push_back(cur->left->val);
count -= cur->left->val;
traversal(cur->left, count); // 递归
count += cur->left->val; // 回溯
path.pop_back(); // 回溯
}
if (cur->right) { // 右 (空节点不遍历)
path.push_back(cur->right->val);
count -= cur->right->val;
traversal(cur->right, count); // 递归
count += cur->right->val; // 回溯
path.pop_back(); // 回溯
}
return;
}
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
result.clear();
path.clear();
if (root == NULL)
return result;
path.push_back(root->val); // 把根节点放进路径
traversal(root, sum - root->val);
return result;
}
};
复杂度
时间复杂度:O(n^2)
空间复杂度:O(n)
Leetcode106 从中序与后序遍历序列构造二叉树
题目链接:从中序与后序遍历序列构造二叉树
思路
步骤如下:
- 第⼀步:如果数组大小为零的话,说明是空节点了。
- 第⼆步:如果不为空,那么取后序数组最后⼀个元素作为节点元素。
- 第三步:找到后序数组最后⼀个元素在中序数组的位置,作为切割点
- 第四步:切割中序数组,切成中序左数组和中序右数组
- 第五步:切割后序数组,切成后序左数组和后序右数组
- 第六步:递归处理左区间和右区间
注意在切割时的边界问题,把握不变量,本题采用左开右闭区间。
代码
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;
}
// 切割中序数组
// 左闭右开区间:[0, delimiterIndex)
vector<int> leftInorder(inorder.begin(),
inorder.begin() + delimiterIndex);
// [delimiterIndex + 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;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0)
return NULL;
return traversal(inorder, postorder);
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
Leetcode105 从前序与中序遍历序列构造二叉树
题目链接:从前序与中序遍历序列构造二叉树
思路
同上题
代码
class Solution {
private:
TreeNode* traversal(vector<int>& inorder, int inorderBegin, int inorderEnd,
vector<int>& preorder, int preorderBegin,
int preorderEnd) {
if (preorderBegin == preorderEnd)
return NULL;
int rootValue = preorder[preorderBegin]; // 注意⽤preorderBegin 不要⽤0
TreeNode* root = new TreeNode(rootValue);
if (preorderEnd - preorderBegin == 1)
return root;
int delimiterIndex;
for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd;
delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue)
break;
}
// 切割中序数组
// 中序左区间,左闭右开[leftInorderBegin, leftInorderEnd)
int leftInorderBegin = inorderBegin;
int leftInorderEnd = delimiterIndex;
// 中序右区间,左闭右开[rightInorderBegin, rightInorderEnd)
int rightInorderBegin = delimiterIndex + 1;
int rightInorderEnd = inorderEnd;
// 切割前序数组
// 前序左区间,左闭右开[leftPreorderBegin, leftPreorderEnd)
int leftPreorderBegin = preorderBegin + 1;
int leftPreorderEnd =
preorderBegin + 1 + delimiterIndex -
inorderBegin; // 终⽌位置是起始位置加上中序左区间的⼤⼩size
// 前序右区间, 左闭右开[rightPreorderBegin, rightPreorderEnd)
int rightPreorderBegin =
preorderBegin + 1 + (delimiterIndex - inorderBegin);
int rightPreorderEnd = preorderEnd;
root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,
preorder, leftPreorderBegin, leftPreorderEnd);
root->right = traversal(inorder, rightInorderBegin, rightInorderEnd,
preorder, rightPreorderBegin, rightPreorderEnd);
return root;
}
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (inorder.size() == 0 || preorder.size() == 0)
return NULL;
// 坚持左闭右开的原则
return traversal(inorder, 0, inorder.size(), preorder, 0,
preorder.size());
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(n)