104.二叉树的最大深度
解题思路:
采用递归来做,首先判断root是否为NULL,然后比较左右数的最大深度,较大的一个+1即可。
int maxDepth(TreeNode* root) {
if(root== NULL)
return 0;
else
return (max(maxDepth(root->left),maxDepth(root->right))+1);
}
226.翻转二叉树
解题思路:翻转二叉树相当于最基础的两个数 1, 2 交换位置成 2,1。那么最常用的操作就要设置一个中间变量temp来存储。
仍然是采用递归的思想,只用考虑root结点的变换情况。
首先,判断root结点是否是空,如果是空直接返回root,
其次,若root不为空,但是left 和 right 结点都是空的话,那么不用翻转,直接返回就root就可以了,
然后,设置一个中间结点temp,将left 和right 进行交换,
最后操作左子树,和右子树,返回root结点即可。
TreeNode* invertTree(TreeNode* root) {
if(root==NULL){
return root;
}
if(root->left==NULL&&root->right==NULL){
return root;
}
TreeNode* temp = root->left;
root->left= root->right;
root->right = temp;
invertTree( root->left) ;
invertTree( root->right) ;
return root;
}
617.合并二叉树
解题思路:采用递归的思想。
两棵树t1,t2,
若t1,t2,均为空,那么直接返回空值。
若t1空,t2不空,则直接返回t2,
若t2空,t1不空,则直接返回t1,
若t1,t2均不为空,则该结点,两者直接相加。
然后再利用递归的思想,去处理该结点的左子树,和右子树。
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(!t1&&!t2)
return NULL;
if(!t1&&t2)
return t2;
if(!t2&&t1)
return t1;
t1->val = t1->val + t2->val ;
t1->left = mergeTrees(t1->left,t2->left);
t1->right = mergeTrees(t1->right,t2->right);
return t1;
}
559.N叉树的最大深度。
解题思路:此题和二叉树的最大深度一样,
首先判断root为空,若空直接返回NULL
不空,则根据递归的思想,只用管下面一层的children
分别来比较,children1 ,... , chidren n 的最大深度,然后再加1 ,就是整个树的最大深度。
这里有一个c ++ trick:
可以直接使用
for (auto n : root->children)
{
temp = max(temp, maxDepth(n));
}
而不使用
for(int i = 0 ; i <root->children.size();i++)
{
temp = max(temp,maxDepth(root->children[i]));
}
int maxDepth(Node* root) {
if(!root) return NULL;
int temp = 0;
for(int i = 0 ; i< root->children.size();i++)
{
temp = max(temp,maxDepth(root->children[i]));
}
return temp+1;
}
589.N叉树的前序遍历。
解题思想:前序遍历,先访问根节点,再访问子节点。
要定义一个 vector<int > res来存放返回的序列。
首先,判断root是否为空,若为空就直接返回 res
其次,在不为空的情况下,先把 root->val 存入res中,
再去遍历每一个children,递归调用前序遍历。
vector<int> res ;
vector<int> preorder(Node* root) {
if(root) {
res.push_back(root->val);
for(auto n : root->children){
preorder(n);
}
}
return res;
}
590.N叉树的后序遍历
和先序遍历一样,直接调用递归法完成,只不过这个是先去管他的子树,再来存储自己的val.
vector<int> res;
vector<int> postorder(Node* root) {
if(root)
{
for(auto n:root->children)
{
postorder(n);
}
res.push_back(root->val);
}
return res;
108.将有序数组转换为二叉搜索树
1,平衡二叉树:空树或者它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树也都是平衡树。
2,二叉搜索树:空树或者二叉树的所有节点比他的左子节点大,比他的右子节点小。
解题思路:由于平衡二叉树和二叉搜索树的定义,我们生成的树满足,左边的肯定比root小,右边的肯定比root大。
这相当于把一个有序的数列,从中间分开,做为根结点,采用递归的思想,左边那一堆再自己去划分,右边的一堆也再自己去划分(递归调用sortedArrayToBST()函数)
这里有个地方第一次没想通,因为对C++的vector不熟悉,vector<int> nums定义了一个容器,num.size()等于其中元素的个数,然后num.begin() + num.size() / 2,我当时想,如果是数组[-10,-3,0,5,9],那num.begin() + num.size() / 2 不是指向0这个元素的位置了吗?再把指针指向的部分转换成数组不是[-10,3,0]了吗?后来去测试了下才知道,原来是一开始指向这个容器的起点,你+1 ,才指向-10的位置,所以是没问题的。
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.empty()) return NULL;
TreeNode* root = new TreeNode(nums[nums.size()/2]);
vector<int> vec_left = vector<int>(nums.begin(),nums.begin()+nums.size()/2 );
vector<int> vec_right = vector<int>(nums.begin()+nums.size()/2 + 1,nums.end());
root->left = sortedArrayToBST(vec_left);
root->right = sortedArrayToBST(vec_right);
return root;
}
700.二叉搜索树中的搜索
解题思路:搜索树,left < root < right,只用判断val和root->val的比较就可以,如果大于就右边继续搜,如果小于就左边搜。
TreeNode* searchBST(TreeNode* root, int val) {
if(!root) return NULL;
if(root->val == val)
return root;
else if (root->val > val)
return searchBST(root->left, val);
else
return searchBST(root->right, val);
}
669.修剪二叉搜索树
解题思路:做了比较多久发现树的题基本上都是递归的思想来解决(比较简单的时候...复杂的还没接触),也不用管它多复杂,到底是多少层,那不是人脑考虑的东西,你就搞的定最基础的那两层,其他的交给电脑去弄就行了。
首先判断是否是空,是就直接返回。
然后不为空的时候,就有个细节,因为我们弄的是二叉搜索树,所以在前面那个题就提到了,二叉搜索树,你右边的一定大于root,左边的一定小于root,所以呢?直接看root->val和L比较,如果root->val比L都小,那直接左边都丢掉,直接去修剪root->right;同理,root->val和R一样。
这时候你只修剪了root,那么接下来还是递归,再修剪左子树和右子树就行了。
最终返回root
TreeNode* trimBST(TreeNode* root, int L, int R) {
if(!root) return NULL;
//tail the root
if(root->val < L)
return trimBST(root->right, L, R);
if(root->val > R)
return trimBST(root->left, L, R);
// tail the children
root->left = trimBST(root->left, L, R);
root->right = trimBST(root->right, L, R);
return root;
}
107.二叉树的层次遍历II
解题思路:层次遍历+倒序。
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode*> q;
vector<vector<int>> res;
if(!root) return res;
q.push(root);
while(!q.empty()){
int size = q.size();
vector<int> a;
for(int i = 0;i< size;i++){
TreeNode* p = q.front();
q.pop();
a.push_back(p->val);
if(p->left) q.push(p->left);
if(p->right) q.push(p->right);
}
res.push_back(a);
}
reverse(res.begin(),res.end());
return res;
}
};
429.N叉树的层序遍历
层序遍历,最基本的操作就是要设置一个队列queue(网上看的),然后把每一层每一层的去访问,好像是BFS(广度优先遍历)。
首先把root放进队列queue之中,当队列queue不为空的时候,说明这一层还没有访问完毕,那么就要一个个的去访问。
每一层都有一个序列啊,所以要定义一个vector<int> a 来存放每一层的序列,进行每一层遍历的时候,首先要定义一个结点,把队列最前面的元素给保存下来,之后把它出队列,然后把这个值存在 a 之中,如果它还有孩纸结点的话,就把它的孩纸结点跟在queue 的后面,循环直到queue为空就结束。最后返回整个vector<vector<int>> 定义的 res 就可以了,里面就存放的是每一层的序列。
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> res ;
queue<Node*> q ;
if(!root) return res;
q.push(root);
while(!q.empty()){
vector<int> a ;
int len = q.size();
// for(int i = 0;i<q.size();i++)
for(int i = 0;i<len;i++)
{
Node* p = q.front();
q.pop();
a.push_back(p->val);
for(auto n : p->children)
{
//a.push_back(n->val);
q.push(n);
}
}
res.push_back(a);
}
return res;
}
257.二叉树的所有路径
解题思路:递归来解决,定义一个vector<stirng> res .首先判断root为空吗?是就直接返回res,如果左孩纸和右孩纸都为空了,说明到达了叶子结点,直接把这个结点存入res就可以了。否则就递归调用寻找路径函数,找到root的左路径和右路径,之后把当前结点加入进去就可以了,就形成了一条从root出发的路径,思想和求二叉树(N叉树)有多少层一样,就是去root + 子树的。
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if(!root) return res;
if(!root->left&&!root->right)
res.push_back(to_string(root->val));
vector<string> leftPath = binaryTreePaths(root->left);
vector<string> rightPath = binaryTreePaths(root->right);
for(auto n : leftPath)
res.push_back(to_string(root->val)+"->" + n);
for(auto n : rightPath)
res.push_back(to_string(root->val)+"->" + n);
return res;
}
637.二叉树的层平均值
解题思路:这个题就是在层序遍历的基础上,加了一个求和而已。不是作为vector<vector<int>>来输出了,而是来用一个vector<int> 来算出每一层的平均值。有个细节要注意,每一层你都要初始化啊!~否则他累加了,计算就出错了。
vector<double> averageOfLevels(TreeNode* root) {
vector<double> res;
queue<TreeNode*> q;
if(!root) return res;
q.push(root);
while(!q.empty())
{
double sum= 0; //detail!!!
int len = q.size();
for(int i = 0;i<len;i++) {
TreeNode* p = q.front();
q.pop();
sum += p->val;
if(p->left) q.push(p->left);
if(p->right) q.push(p->right);
}
res.push_back((double)sum / len);
}
return res;
}
872.叶子相似的树
解题思路:先写一个找叶子结点的函数,递归的来做,
首先判断root是不是空?空就直接返回res
然后看看是不是叶子结点,是就把这个值存入序列res中,
不是的话,就找这个结点的左子树,右子树,递归就可以了。
最后返回res。
这里res定义的时候是用的引用,vector<int> &res,在函数体内会改变。还有一个积累是,vector 对 == 进行了重载,直接计算就可以了。不用一位一位的去重新搞。
vector<int> findTheLeaves(vector<int> &res,TreeNode* root){
if(!root) return res;
if(!root->left&&!root->right)
res.push_back(root->val);
findTheLeaves(res,root->left);
findTheLeaves(res,root->right);
return res;
}
bool leafSimilar(TreeNode* root1, TreeNode* root2) {
vector<int> rootRes1 ;
vector<int> rootRes2 ;
rootRes1 = findTheLeaves(rootRes1,root1);
rootRes2 = findTheLeaves(rootRes2,root2);
if(rootRes1 == rootRes2)
return true;
else
return false;
}