根据树的特殊性进行验证
110. 平衡二叉树
根据平衡二叉树条件,从根节点出发看左右子树高度,在递归看左右子树是不是平衡二叉树
class Solution {
public:
bool isBalanced(TreeNode* root) {
if(!root) return true;
int left = height(root->left);
int right = height(root->right);
if(abs(left - right) >= 2) return false;
return isBalanced(root->left) && isBalanced(root->right);
}
int height(TreeNode * root){
if(!root) return 0;
return max(height(root->left), height(root->right)) + 1;
}
};
递归找特定叶子节点
404. 左叶子之和
整体遍历(前中后序都可以,因为不涉及出栈节点的特殊操作)从爷爷的视角来找这个左叶子
class Solution {
public:
int sum = 0;
int sumOfLeftLeaves(TreeNode* root) {
dfs(root);
return sum;
}
void dfs(TreeNode * root){
if(!root) return;
if(!root->left && !root->right) return;
if(root->left && !root->left->left && !root->left->right) sum += root->left->val;
dfs(root->left);
//if(root->left && !root->left->left && !root->left->right) sum += root->left->val;
dfs(root->right);
//if(root->left && !root->left->left && !root->left->right) sum += root->left->val;
}
};
1.递归
题目 在树的最后一行找到最左边的值。也就是深度最大的叶节点的第一个值
任何一种遍历都行(前序 中序,后序因为不涉及拿出节点时的操作)只要是保证左优先即可
2. 层序遍历,判断是不是最后一层的第一个值
class Solution {
public:
int depth_max = -1;
int value;
int findBottomLeftValue(TreeNode* root) {
dfs(root, 0);
return value;
}
void dfs(TreeNode* root, int depth){
if(!root) return;
if(!root->left && !root->right){
if(depth_max < depth){
value = root->val;
depth_max = depth;
}
}
dfs(root->left, depth+1);
dfs(root->right, depth+1);
}
};
**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;
}
};**
构造二叉树
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。(如果是前序数组那就是第一个元素作为节点元素,在中序数组中找位置)
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return build(inorder, postorder, 0, inorder.size()-1, 0, postorder.size()-1);
}
TreeNode* build(vector<int>& inorder, vector<int>& postorder, int inorder_l, int inorder_r, int postorder_l, int postorder_r){
if(inorder_l > inorder_r) return nullptr;
int mid;
for(int i = inorder_l; i<= inorder_r; i++){
if(inorder[i] == postorder[postorder_r]){
mid = i;
}
}
TreeNode * node = new TreeNode(inorder[mid]);
node->left = build(inorder, postorder, inorder_l, mid-1, postorder_l, postorder_l + (mid - inorder_l-1));
node->right = build(inorder, postorder, mid+1, inorder_r, postorder_l + mid - inorder_l, postorder_r-1);
return node;
}
};
654. 最大二叉树
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,最大元素作为节点元素,并且作为切割点,切割左右子树
第三步:递归的生成左右子树
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return build(nums, 0, nums.size()-1);
}
TreeNode*build(vector<int>&nums, int left, int right){
if(left > right) return nullptr;
int max = nums[left];
int mid = left;
for(int i=left; i<=right; i++){
if(nums[i] > max){
max = nums[i];
mid = i;
}
}
TreeNode *node = new TreeNode(nums[mid]);
node->left = build(nums, left, mid-1);
node->right = build(nums, mid+1, right);
return node;
}
};
如果没有返回值,只是一味的看value root1->val += root2->val; 很容易造成重复叠加,不好判断。
步骤一:当前值修改
步骤二:递归建立左子树
步骤三:递归建立右子树
递归出口:两个都为空, 一方未空返回另一端
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(!root1 && ! root2) return nullptr;
if(root1 && root2){
root1->val += root2->val;
root1->left = mergeTrees(root1->left, root2->left);
root1->right = mergeTrees(root1->right, root2->right);
}
if(!root1) return root2;
return root1;
}
};
路径回溯
257. 二叉树的所有路径
回溯 问题就在于string的回溯 注意递归几次就回溯几次
cur 记录该递归整体回溯的位置
now 记录的访问左右子树之后的回溯位置
class Solution {
public:
vector<string>result;
string path;
vector<string> binaryTreePaths(TreeNode* root) {
dfs(root);
return result;
}
void dfs(TreeNode * root){
if(!root) return;
string cur = path;
path = path + to_string(root->val);
if(!root->left&& !root->right){
result.push_back(path);
return;
}
path = path + "->";
string now = path;
if(root->left){
dfs(root->left);
path = now;
}
if(root->right){
dfs(root->right);
path = now;
}
path = cur;
}
};
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
if(!root->left && !root->right){
if(targetSum == root->val) return true;
}
return hasPathSum(root->left, targetSum - root->val)||
hasPathSum(root->right, targetSum- root->val);
}
};
class Solution {
public:
vector<vector<int>>result;
vector<int>path;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(!root) return result;
path.push_back(root->val);
dfs(root, targetSum-root->val);
return result;
}
void dfs(TreeNode* root, int targetSum){
if(!root) return;
if(!root->left && !root->right && targetSum == 0){
result.push_back(path);
return;
}
if(root->left){
path.push_back(root->left->val);
dfs(root->left, targetSum - root->left->val);
path.pop_back();
}
if(root->right){
path.push_back(root->right->val);
dfs(root->right, targetSum - root->right->val);
path.pop_back();
}
}
};
- 路径总和 III