100 相同的树
题目
给定两棵二叉树的根节点,判断两棵二叉树是否相等。
思路
递归的思路是判断两棵二叉树的左右子树是否相等,当两棵二叉树的对应位置不相同时,返回false,与判断二叉树是否镜像对称类似,只不过从一棵树变成了两棵树。
递归终止的条件,需要分指针为空和不为空的情况,指针为空分为①二叉树1指针为空,树2指针不为空,返回false;②树1不为空,树2为空,返回false;③树1 树2都为空,返回true;则剩下的情况就是两棵树对应节点都不为空,此时如果两树节点所指的值不同,则返回false;接着就只剩下两树节点所指的值相同的情况,这时只要递归判断它们的左右孩子是否相同即可。
代码
/**
* 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 isSameTree(TreeNode* p, TreeNode* q) {
if(!p && !q)
return true;
else if(!p && q)
return false;
else if(p && !q)
return false;
else if(p->val != q->val)
return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
};
404 左叶子之和
题目
计算给定二叉树的左叶子之和。
思路
解决问题的关键是怎样判断是左叶子节点。首先需要有父节点,此节点是父节点的左孩子,然后此节点的左右孩子为空,此时它为左叶子节点。
①用递归的思路,函数参数为根节点,返回左叶子节点和;递归的终止条件为当前根节点为空,返回0;单次递归时,当该节点为左叶子节点时,记录节点值,然后递归求左子树和右子树左叶子之和,相加变为整个树的左叶子之和。
②迭代:可以按照先序遍历的顺序遍历,判断当前节点的左孩子是否为叶子节点,是则累加,不是则继续遍历。
代码
递归:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(!root) return 0;
int sum = 0;
if(root->left && !root->left->left && !root->left->right)
sum = root->left->val;
return sum + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
};
迭代:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(!root) return 0;
stack<TreeNode*> st;
int sum = 0;
st.push(root);
while(!st.empty()) {
TreeNode* cur = st.top();
st.pop();
if(cur->left && !cur->left->left && !cur->left->right)
{
sum +=cur->left->val;
}
if(cur->right)
st.push(cur->right);
if(cur->left)
st.push(cur->left);
}
return sum;
}
};
513 找树左下角的值
题目
找到二叉树的最左边的叶子节点的值。
思路
①层序遍历,只需要返回最后一层的第一个节点值即可。
②用递归的思路,因为要找的是最左边的叶子节点,也就是要找到深度最大的点,按照先序遍历的话,找到的深度最大的点就是最左边的节点值。
代码
层序遍历
/**
* 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;
int res;
if(!root)
return 0;
que.push(root);
while(!que.empty()) {
int size = que.size();
int i = size;
while(size--) {
TreeNode* cur = que.front();
que.pop();
if(size == i - 1) res = cur->val;
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return 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 maxLen = INT_MIN;
int maxLenValue;
void getDepth(TreeNode* root,int depth) {
if(!root)
return ;
if(!root->left && !root->right)
{
if(depth > maxLen)
{
maxLen = depth;
maxLenValue = root->val;
}
return ;
}
if(root->left)
getDepth(root->left,depth + 1);
if(root->right)
getDepth(root->right,depth + 1);
return ;
}
int findBottomLeftValue(TreeNode* root) {
getDepth(root,0);
return maxLenValue;
}
};
112 路径总和
题目
给定目标值target,判断树中是否存在根节点到叶子节点的路径和等于目标值。
思路
遍历从根节点到叶子节点的路径,判断路径和是否等于目标值,怎样判断是否等于,可以采用目标值递减的方法。
递归的思路:参数是根节点和目标值,返回bool,递归的终止条件是当根节点为空时,没有值,自然不能等于目标值返回false;每次递归,先判断是否是叶子节点,是的话判断当前目标值和节点值是否相等,相等则返回true,不相等返回false;如果不是叶子节点,则递归判断它的左右子节点是否满足要求。要注意的是目标值需要进行回溯,判断完左节点是否满足要求后,判断右节点时的目标值需要和判断左节点的相同。
代码
/**
* 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 hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
if(!root->left && !root->right && targetSum == root->val)
return true;
if(!root->left && !root->right)
return fasle;
return hasPathSum(root->left,targetSum - root->val) || hasPathSum(root->right,targetSum - root->val);
}
};
113 路径总和Ⅱ
题目
找到二叉树中所有根节点到叶子节点的路径和等于目标值的路径。
思路
与上一题类似,不过需要做的是保存所有符合条件的路径。用一个二维数组来保存所有满足条件的路径,一个一维数组表示当前路径。
代码
/**
* 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:
void findPath(TreeNode* root,int targetSum,vector<int>& path,vector<vector<int>>& res) {
path.push_back(root->val);
if(!root->left && !root->right && targetSum == root->val) {
res.push_back(path);
return ;
}
if(!root->left && !root->right)
return ;
if(root->left) {
findPath(root->left,targetSum - root->val,path,res);
path.pop_back();
}
if(root->right) {
findPath(root->right,targetSum - root->val,path,res);
path.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<int> path;
vector<vector<int>> res;
if(!root) return res;
findPath(root,targetSum,path,res);
return res;
}
};
106 从中序与后序遍历序列构造二叉树
思路
从后序遍历可以得出根节点,然后根据根节点从中序遍历序列中把左子树和右子树分开,然后再从后序序列中得到分开的子树的根节点,这样一层一层分下去。
代码
/**
* 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:
TreeNode* build(vector<int>& inorder,int inBegin,int inEnd,vector<int>& postorder,int postBegin,int postEnd) {
if(postEnd == postBegin)
return nullptr;
TreeNode* root = new TreeNode(postorder[postEnd - 1]);
if(postEnd - postBegin == 1)
return root;
int i = inBegin;
for(;i < inEnd;i++)
if(inorder[i] == postorder[postEnd - 1])
break;
int leftInBegin = inBegin;
int leftInEnd = i;
int rightInBegin = i + 1;
int rightInEnd = inEnd;
int leftPostBegin = postBegin;
int leftPostEnd = postBegin + leftInEnd - leftInBegin;
int rightPostBegin = leftPostEnd;
int rightPostEnd = postEnd - 1;
root->left = build(inorder,leftInBegin,leftInEnd,postorder,leftPostBegin,leftPostEnd);
root->right = build(inorder,rightInBegin,rightInEnd,postorder,rightPostBegin,rightPostEnd);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return build(inorder,0,inorder.size(),postorder,0,postorder.size());
}
};
105 从前序与中序遍历序列构造二叉树
思路
与上题思路相同。
代码
/**
* 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:
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(preEnd - preBegin == 1) return root;
int i = inBegin;
for(;i < inEnd;i++)
if(inorder[i] == preorder[preBegin])
break;
int leftInBegin = inBegin;
int leftInEnd = i;
int rightInBegin = i + 1;
int rightInEnd = inEnd;
int leftPreBegin = preBegin + 1;
int leftPreEnd = leftPreBegin + leftInEnd - leftInBegin;
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) {
return traversal(preorder,0,preorder.size(),inorder,0,inorder.size());
}
};
654 最大二叉树
思路
只需要递归找到数组最大值,先构造根节点,再分别构造左右子树。
代码
/**
* 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:
pair<int,int> max(const vector<int>& nums,int begin,int end){
pair<int,int> res(INT_MIN,-1);
for(int i = begin;i < end;i++) {
if(nums[i] > res.first) {
res = {nums[i],i};
}
}
return res;
}
TreeNode* build(vector<int>& nums,int begin,int end) {
if(begin >= end)
return nullptr;
pair<int,int> Max = max(nums,begin,end);
TreeNode* root = new TreeNode(Max.first);
int leftBegin = begin;
int leftend = Max.second;
int rightBegin = Max.second + 1;
int rightEnd = end;
root->left = build(nums,leftBegin,leftend);
root->right = build(nums,rightBegin,rightEnd);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return build(nums,0,nums.size());
}
};