LeetCode——树

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;
        
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值