LeetCode算法打卡--树

129. 求根到叶子节点数字之和

给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。

例如,从根到叶子节点路径 1->2->3 代表数字 123。

计算从根到叶子节点生成的所有数字之和。

说明: 叶子节点是指没有子节点的节点。


链接:https://leetcode-cn.com/problems/sum-root-to-leaf-numbers
 

/*基本思想:递归的基本思想
*/
/**
 * 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 del(TreeNode* root,int sum)
    {
       
        if(root == NULL) return 0;
        sum = sum * 10 + root->val;
        if(root->left == NULL && root->right == NULL) return sum;
        return del(root->left, sum) + del(root->right, sum);

    }
    int sumNumbers(TreeNode* root) {
        return del(root,0);
    }
};

112. 路径总和

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

链接:https://leetcode-cn.com/problems/path-sum/

/*基本思想:左右别求和 有一方ture即为true
*/
/**
 * 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:
    bool del(TreeNode* root,int sum ,int target)
    {
          
        if(root == NULL)
          return false; 
         sum+=root->val;
        if(sum == target && root->left == NULL && root->right==NULL)
          return true;  
      
        return del(root->left,sum,target) || del(root->right,sum,target);
    }
    bool hasPathSum(TreeNode* root, int sum) {
       return del(root,0,sum);
    }
};

113. 路径总和 II

给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。

说明: 叶子节点是指没有子节点的节点。

链接:https://leetcode-cn.com/problems/path-sum-ii/

/*基本思想:回溯的基本思想,注意当到达叶子节点时,满足条件等于target需要返回上一层,进行sum和cur的操作,不满足条件也需要返回上一层,每次都是深度遍历,找到叶子
*/
/**
 * 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:

    void del(TreeNode* root,int sum ,int target,vector<int> &cur,vector<vector<int>> &res)
    {
       
       sum+=root->val;
       cur.push_back(root->val);
       if(sum == target && root->left==NULL && root->right == NULL )
       {
           res.push_back(cur);
           sum-=root->val;
           cur.pop_back();
       }

       else
       {
              
           if(root->left!=NULL)
             del(root->left,sum,target,cur,res);
           
           if(root->right!=NULL)
             del(root->right,sum,target,cur,res);
           sum-=root->val;
           cur.pop_back();
       }
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<int> cur;
        vector<vector<int>> res;
        if(root == NULL)
            return res;
        del(root,0,sum,cur,res);
        return res;
    }
};

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

链接:https://leetcode-cn.com/problems/balanced-binary-tree/

 

/*基本思想,先递归计算某个节点的左右子树的高度,差值大于1 返回false
          计算子树高度的时候,以他的左右子树最大的为该子树的高度
*/

/**
 * 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  high(TreeNode* root)
    {
        if (root == NULL)
            return 0;
        int left_high = high(root->left)+1;
        int right_high = high(root->right)+1;
        return max(left_high,right_high);
    }
    bool isBalanced(TreeNode* root) {
          
          if(root==NULL)
            return true;
          if(abs(high(root->left) - high(root->right)) > 1)
             return false;
          return isBalanced(root->left) && isBalanced(root->right);

    }
};

100. 相同的树

给定两个二叉树,编写一个函数来检验它们是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

链接:https://leetcode-cn.com/problems/same-tree/

/*基本思想:当节点不为空 就判断两个节点值相同的情况下,递归判断两个节点的左右子树是否都相同,不相等,返回false
           当节点都为空,返回TRUE
           否则返回false
*/
/**
 * 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:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        
        if(p!=NULL && q!=NULL)
        {
            if(q->val==p->val)
                return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
            else
                return false;
        }
        if(p==NULL && q==NULL)
            return true;

      return false;
    }
};

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

链接:https://leetcode-cn.com/problems/symmetric-tree/

/*基本思想:判断左子树的左节点等于右子树的右节点,左子树的右节点等于右子树的左节点,即为对称二叉树
           所以判断一个树,传递他的左子树和右子树
           可以用递归和迭代两种方法:迭代的时候要借助栈,每次将两种情况都放进去栈中只要栈不为空就一直判断
*/

/**
 * 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: 
    /*bool del(TreeNode*L , TreeNode*R)
    {
        
        if(R!=NULL && L!=NULL)
            {
                if(R->val == L->val)
                    return del(L->left,R->right) && del(L->right,R->left);
                else
                   return false;
            }
        if(R== NULL && L==NULL)
           return true;
        
        return false; 
    }
    bool isSymmetric(TreeNode* root) {
        if(root == NULL)
          return true;
        else
          return del(root->left,root->right);
    }
    */
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;   //空树是对称的
        stack<TreeNode *> s;
        TreeNode *L=root->left,*R=root->right;
         s.push(L);
         s.push(R);        //即使是空节点,也是可以push到栈里的,栈并不为空。
      while(!s.empty())
      {
          L=s.top();
          s.pop();
          R=s.top();
          s.pop();
          
          if(!L && !R) continue;            //L、R都是空节点
          if(!L || !R) return false;        //有一个为空,不对称
          if(L->val!=R->val) return false;  //值不相等,不对称
          
          s.push(L->left);
          s.push(R->right);
          s.push(L->right);
          s.push(R->left);
      }
      return true;
    

    }
};

98. 验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。


链接:https://leetcode-cn.com/problems/validate-binary-search-tree

/*基本思想:主要是设置上下界,对于左子树的节点,必须全部小于根节点,所以上界是根,对于右子树,必须所有节点大于根节点,所以下界是根
 注意最小值和最大值int取到的情况,此处用long int避免
   方法二:中序遍历。序列递增则为BST。
*/
/**
 * 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:
    /*bool del(TreeNode * root , long int minval, long int maxval)
    {
      if(root==NULL)
          return true;
      if(root->val <= minval || root->val>=maxval)
          return false;
      return del(root->left,minval,root->val) && del(root->right,root->val,maxval);
    }
    bool isValidBST(TreeNode* root) {
       
       return del(root,INT64_MIN,INT64_MAX);

    }*/

   
    vector<int> v;
    void midTrav(TreeNode *root)
    {
        if(root==NULL)
            return;
        midTrav(root->left);
        v.push_back(root->val);
        midTrav(root->right);
    }
    bool isValidBST(TreeNode *root) {
        if(root==NULL)
            return true;
        midTrav(root);
        int len = v.size();
        for(int i=0;i<len-1;i++)
        {
            if(v[i]>=v[i+1])
                return false;
        }
        return true;
    }
};

124. 二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

链接:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/

/*基本思想:求解的结果作为每次递归的中间值碰到大了就更新,对于中间节点作为当前节点作为根节点最大值是左子树的最大值+右子树的最大值,更新结果,但是函数的返回值应该只能返回左右子树中的最大的,因为从当前节点出发只能到达左右一边
*/
/**
 * 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 maxvalue = INT_MIN;
    int maxsum(TreeNode *root)
    {
        if(root == NULL)
            return 0;
        int leftsum = maxsum(root->left);
        int rightsum = maxsum(root->right);
        int sum = root->val;
        //对于当前节点为根节点,他的和的最大值应该是加上左子树的最大值和右子树的最大值
        if(leftsum>0)
           sum += leftsum;
        if(rightsum>0)
           sum += rightsum;
        if(sum>maxvalue)
            maxvalue = sum;
        return max(0,max(leftsum,rightsum)+root->val);//只能返回左右子树中较大值加上root.val,因为对于从根节点出发只能到达左右中的一个

    }
    int maxPathSum(TreeNode* root) {
        if(root == NULL)
           return 0;
        maxsum(root);
        return maxvalue;
        
    }
};

687. 最长同值路径

给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

注意:两个节点之间的路径长度由它们之间的边数表示。

链接:https://leetcode-cn.com/problems/longest-univalue-path/

/*基本思想: 每个节点当作根节点计算最大值=左最大+右最大,中间用maxres纪录,但是返回应该是左右中的一个
*/
/**
 * 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 maxres = 0;
    int findmax(TreeNode* root)
{
      if(!root) return 0;
      int left = 0;
      int right = 0;   
      left = findmax(root->left);
      right = findmax(root->right);
        if(root->left && root->right){
        if(root->val == root->left->val && root->val == root->right ->val){
           maxres =max(maxres, 2 + left + right);
           return max(1+left, 1+right) ;
        }
        }
        if (root->left && root->val == root->left->val )
        {
            maxres = max(maxres, 1+left);
            return left+1;
        }
        if( root->right && root->val == root->right->val) 
        {
            maxres = max(maxres, 1+right );
            return 1+right ;
        } 
        return 0;
        
}
    int longestUnivaluePath(TreeNode* root) {
      
         if(root == NULL)
            return 0;

         findmax(root);
        return maxres;
     
    }
};

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

/*基本思想:基本的递归,左右分别递归求最大
*/
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode *root) {
        if(root == NULL)
            return 0;
        int left_depth = maxDepth(root->left);
        int right_depth = maxDepth(root->right);
        return max(left_depth,right_depth)+1;
    }
};

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

链接:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/

/*基本思路: 递归判断左右最小的,如果左右都有,则取最小的加上本节点,否则只有左子树,就左子树的结果加上本节点,否则就是右子树的结果加上本节点
*/
/**
 * 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 minDepth(TreeNode* root) {
       if(root==NULL)
          return 0;
       if(root->left && root->right)
          return 1+(min(minDepth(root->left),minDepth(root->right)));
        if(root->left)
          return 1+minDepth(root->left);
        if(root->right)
           return 1+minDepth(root->right);
        return 1;  
    }
};

 

94. 二叉树的中序遍历

给定一个二叉树,返回它的中序 遍历。

链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

/*基本思想:递归和迭代,迭代使用栈辅助实现,先一直把左子树进栈,之后找右子树
*/
/**
 * 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:
 /*
    void inorder(TreeNode* root , vector<int> &r)
    {
        if(root == NULL)
            return;
        inorder(root->left,r);
        r.push_back(root->val);
        inorder(root->right,r);
    }

    vector<int> inorderTraversal(TreeNode* root) {
     vector<int> r;
     inorder(root,r);
     return r;   
    }
    */

   vector<int> inorderTraversal(TreeNode *root)
   {
       stack<TreeNode*> s;
       vector<int> r;
       TreeNode *t = root;
       while(t || !s.empty() )
       {
          while(t!= NULL)
          {
              s.push(t);
              t = t->left;
          }
          
          if(!s.empty()){ 
          r.push_back(s.top()->val);
          t = s.top()->right;
          s.pop();
        }
       }
       return r;

            
       }
   

};

144. 二叉树的前序遍历

给定一个二叉树,返回它的 前序 遍历。

链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/


/*基本思想:递归和迭代,迭代利用栈,每次放入root->val之后,先放root->right,然后再放root->left,这样出栈就是先出左,再出右
*/
/**
 * 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:
    /*
    void preorder(TreeNode *root, vector<int> &res)
    {
         if(root == NULL)
        {
            return ;
        }
        
        res.push_back(root->val);
        preorder(root->left,res);
        preorder(root->right,res);
        
    }
   
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        preorder(root,res);
        return res;
     } */

     vector<int> preorderTraversal(TreeNode* root)
     {
       
         stack<TreeNode*> s;
         
         vector<int> res; 
         if(root==NULL)
           return res;
         s.push(root);
 
         while(!s.empty())
         {
             TreeNode* t = s.top();
             s.pop();
             res.push_back(t->val);
              if(t->right)
               s.push(t->right);
             if(t->left)
                s.push(t->left);
           

           
         }
         return res;
     }  
};

145. 二叉树的后序遍历

给定一个二叉树,返回它的 后序 遍历。

链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

/*基本思想:递归和迭代,迭代可以仿照前序遍历,只需要最后反转一下就可以了
*/
/**
 * 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:
/*
    void postorder(TreeNode* root, vector<int> & res)
    {
        if(root == NULL)
           return ;
        postorder(root->left,res);
        postorder(root->right,res);
        res.push_back(root->val);

    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        postorder(root,res);
        return res;
    }
    */
   vector<int> postorderTraversal(TreeNode* root) {
      stack<TreeNode*> s;
      vector<int> res;
    
    if(root == NULL)
    return res;
      s.push(root);
      while(!s.empty())
      {
          TreeNode* tmp = s.top();
           res.push_back(tmp->val);
          s.pop();
          if(tmp->left)
           s.push(tmp->left);
          if(tmp->right)
           s.push(tmp->right);

      }
      reverse(res.begin(),res.end());
      return res;
   
   } 
};

 

109. 有序链表转换二叉搜索树

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。


链接:https://leetcode-cn.com/problems/convert-sorted-list-to-binary-search-tree
 

/*基本思想:对于链表首先要找到中点,找到中点后,要以中点的值建立一个数的根节点,然后需要把原链表断开,分为前后两个链表,都不能包含原中节点,然后再分别对这两个链表递归调用原函数,分别连上左右子节点即可。
*/
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * 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:
    TreeNode* ListToBST(ListNode* head, ListNode *tail) {
        
       if (head == tail)
            return NULL;
        ListNode * fast = head;
        ListNode * low =head;
        while(fast!=tail && fast->next!=tail  )
        {
           fast = fast->next->next;
           low = low->next;
        }
        
        TreeNode *root,*lchild,*rchild;
       
        root = new TreeNode(low->val);
        root->left = ListToBST(head,low);
        root->right = ListToBST(low->next,tail);
        
        return root;
    }
    TreeNode* sortedListToBST(ListNode* head) {
        return ListToBST(head,NULL);
    }
    
};

102. 二叉树的层次遍历

给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。

链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

/*
  基本思想:利用队列来实现,每次取队头,然后把他的左孩子和右孩子都放入队列,用一个队列记录他们所在的层数,在同一层,就放入同一个vector
    不在同一层,先把之前的vector放入结果,然后再重新放入vector
*/

/**
 * 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:
    vector<vector<int>> levelOrder(TreeNode* root) {
      
        vector<vector<int>> res; 
        queue<TreeNode*> q;
        queue<int> num;
        if(root == NULL)
            return res;
       
        q.push(root);
        num.push(1);
        int preindex = 1;
        vector<int> cur;
        while(!q.empty())
        {
            
            TreeNode *t = q.front();
           
            int index = num.front();
            if(index == preindex)
            {
                 cur.push_back(t->val);
            }
            else
            {
                res.push_back(cur);
                cur.clear();
                cur.push_back(t->val);
                
            }
            q.pop();
            num.pop();
            if(t->left!=NULL)
            {
                q.push(t->left);
                num.push(index+1);
                
            }
            if(t->right!=NULL)
            {
                q.push(t->right);
                num.push(index+1);
            }
            preindex = index;
            
           
        }
        res.push_back(cur);
        return res;
    }
};

96. 不同的二叉搜索树

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

链接:https://leetcode-cn.com/problems/unique-binary-search-trees/

/*基本思想: 动态规划,对于1到n的数字,dp[n]可以选择任何一个数字作为根,当选择k为根的时候,二叉搜索树的数量为左子树的数量*右子树的数量
            左子树都是比k小的,所以数量就是dp[k-1] ,右子树都是比k大的,所以数量为dp[n-k]
            所以对于每一个k累加就是n对应的数量
            设dp[i]表示共有i个节点时,能产生的BST树的个数
            i == 0 时,空树的个数必然为1,因此dp[0] = 1
            i == 1 时,只有1这个根节点,数量也为1,因此dp[1] = 1
            i == 2 时, dp[2] = dp[0] * dp[1] + dp[1] * dp[0]
            dp[n]=  k为1-n所有情况累加: dp[k-1]*dp[n-k]
            以此类推
*/
class Solution {
public:
    int numTrees(int n) {
        int dp[n+1];
        dp[0]=1;
        dp[1]=1;
        for(int i=2;i<=n;i++)
        {
            dp[i]=0;
            for(int j=1; j<=i;j++)
            {
                dp[i] += dp[j-1]*dp[i-j];
            }
        }
        return dp[n];
    }
};

 

5. 不同的二叉搜索树 II

给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树

链接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii/


/*基本思路:每次一次选取一个结点为根,然后递归求解左右子树的所有结果,最后根据左右子树的返回的所有子树,依次选取然后接上(每个左边的子树跟所有右边的子树匹配,而每个右边的子树也要跟所有的左边子树匹配,总共有左右子树数量的乘积种情况),构造好之后作为当前树的结果返回
/**
 * 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:
     vector<TreeNode*> tree( int start,int end)
    {
        vector<TreeNode*>  res;
        
        if(start>end)
        {
         
           res.push_back(NULL);
           return res;
        }
        for(int i=start;i<=end;i++)  //以i为根节点的树,其左子树由[1, i-1]构成, 其右子树由[i+1, n]构成。该原则建树具有唯一性
        {

            vector<TreeNode*> left_res = tree(start,i-1);
            vector<TreeNode*> right_res = tree(i+1,end);
             //每个左边的子树跟所有右边的子树匹配,而每个右边的子树也要跟所有的左边子树匹配,总共有左右子树数量的乘积种情况
            int lsize = left_res.size();
            int rsize = right_res.size();
            for(int j=0;j<lsize;j++){
                for(int k=0;k<rsize;k++){
                    TreeNode *root = new TreeNode(i);
                    root->left = left_res[j];
                    root->right = right_res[k];
                    res.push_back(root);
                }
            }
        }
         return res;
    }
    vector<TreeNode*> generateTrees(int n) {
         
          vector<TreeNode*>  res;
          if(n==0)
            return res;
          return tree(1,n);
    }
};

99. 恢复二叉搜索树

二叉搜索树中的两个节点被错误地交换。

请在不改变其结构的情况下,恢复这棵树。

链接:https://leetcode-cn.com/problems/recover-binary-search-tree/

/*基本思想:中序遍历的应用:记录三个指针:pre表示前一个数,first表示第一个要交换的,second表示第二个要交换的
           根据二叉搜索树的性质,对于root,pre指向他的前一个节点,一定要比他小,当比他大的时候,证明这个pre出错,所以first就是该pre
           然后当确定了first之后,root之后的一定是比他大的,所以对于要交换的位置,一定是root之后比他小的,否则就是root。递归寻找最小的root。
           然后遍历之后交换first和second即可

           方法二:先中序遍历存储,然后排序,最后填树
*/
/**
 * 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:
    
    void Inorder(TreeNode *root,vector<int> &vec,vector<TreeNode *> &node)
{
    if(!root)
       return;
    Inorder(root->left,vec,node);
    vec.push_back(root->val);
    node.push_back(root);
    Inorder(root->right,vec,node);
}
void recoverTree(TreeNode *root)
{
    vector<int> vec;
    vector<TreeNode *> node;
    Inorder(root,vec,node);
    sort(vec.begin(),vec.end());
    for(int i=0;i<vec.size();i++)
        node[i]->val = vec[i];
}/*
    TreeNode *pre=new TreeNode(INT_MIN);
    TreeNode *first=NULL;
    TreeNode *second=NULL;
    void inorder(TreeNode *root)
    {
          if(root == NULL)
              return;
          inorder(root->left);
          if(first == NULL && pre->val > root->val)
             first  = pre;
          if(first != NULL && pre->val > root->val)   //
             second = root;
          pre= root;
          inorder(root->right);
          
    }
    void recoverTree(TreeNode* root) {
        if(root==NULL)
            return ;
        inorder(root);
        swap(first->val,second->val);
    }*/
};

108. 将有序数组转换为二叉搜索树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/

/*基本思想:二分法,根据二叉搜索树的特点,对于有序数组,就是中点为根,左右是他的左右子树,递归构造就好
*/
/**
 * 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:
    TreeNode* BST(vector<int>& nums, int start,int end)
    {
         if(start>=end)
            return NULL;
         int m =(start+end)/2;
         TreeNode *root =new TreeNode(nums[m]);
         root->left = BST(nums,start,m);
         root->right = BST(nums,m+1,end);
         return root;
  
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        TreeNode* root;
        root = BST(nums,0,nums.size());
        return root;
        
    }
};

105. 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

/*基本思想:递归,根据前序遍历和中序遍历的特点,分别找到左子树和右子树的前序和中序递归就好*/
/**
 * 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:
    
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() ==0 || inorder.size()==0)
          return NULL;
        TreeNode *root = new TreeNode(preorder[0]);
        vector<int> lpre,rpre,lin,rin;
        int j=1;
        int i;
        for(i=0;i<inorder.size();i++)
        {
            
            if(inorder[i]==preorder[0])
              break;
            lpre.push_back(preorder[j++]);
            lin.push_back(inorder[i]);
        }
        for(i=i+1;i<inorder.size();i++)
        {
           rin.push_back(inorder[i]);
           rpre.push_back(preorder[j++]);
        }
        
        root->left = buildTree(lpre,lin);
        root->right = buildTree(rpre,rin);
        return root;
    }
};

06. 从中序与后序遍历序列构造二叉树

根据一棵树的中序遍历与后序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

链接:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

/*基本思想:递归,和前序思想一样,只不过后序遍历的根是最后一个,根据构建规则分别找到左右子树的中序和后序递归就好
*/
/**
 * 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:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0 || postorder.size()==0)
           return NULL;
        int len = postorder.size();
        
        TreeNode *root = new TreeNode(postorder[len-1]);
        int i;
        vector<int> lin;
        vector<int> rin;
        vector<int> lpost;
        vector<int> rpost;
        int j=0;
        for(i=0;i<inorder.size();i++)
        {
            if(inorder[i] == postorder[len-1])
               break;
            lin.push_back(inorder[i]);
            lpost.push_back(postorder[j++]);
        }
      
       

        for(i=i+1;i<inorder.size();i++)
        {
            rin.push_back(inorder[i]);
            rpost.push_back(postorder[j++]);
        }
        root->left = buildTree(lin,lpost);
        root->right = buildTree(rin,rpost);
        return root;
    }
};

103. 二叉树的锯齿形层次遍历

给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

链接:https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/

/*基本思想:相当于层次遍历,每次一层存入到一个vector,然后两个放节点的vector,第一个遍历存值,存孩子节点到第二个vector,然后用第二个vector替换第一个,继续找孩子,直到没有孩子结束为止,最后对偶数行进行反转输出就好(注意偶数行对应下标是奇数)
*/
/**
 * 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:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {

       vector<TreeNode*> r1;
       r1.push_back(root);
       vector<TreeNode*> r2;
       vector<vector<int>> res;
       vector<int> cur;
       if(root==NULL)
           return res;
       while(r1.size()!=0)
       {
          
           for(int i=0;i<r1.size();i++)
           {
              cur.push_back(r1[i]->val);
             if(r1[i]->left !=NULL)
                  r2.push_back(r1[i]->left);
             if(r1[i]->right !=NULL)
                  r2.push_back(r1[i]->right);
           }
           r1 = r2;
           r2.clear();
           res.push_back(cur);
           cur.clear();
       } 
       for(int i=0;i<res.size();i++)
       {
           if(i%2!=0)
              reverse(res[i].begin(),res[i].end());
       }
       return res;
    }
};

114. 二叉树展开为链表

给定一个二叉树,原地将它展开为链表。

链接:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/

/*基本思想:递归,先把左右子树都捋直,然后把左子树移动到节点的右子树上,最后把原来的右子树接到后面,注意接的时候要找到最后一个节点去接
*/
/**
 * 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:
    void flatten(TreeNode* root) {

       if(root == NULL)
           return ;
        //先把左右子树捋直
       flatten(root->left);
       flatten(root->right);       
       TreeNode* tmp;
       tmp = root->right;     
       if(root->left){
            root->right = root->left;
            root->left = NULL;
            while(root->right)
              root = root->right;
            root->right = tmp;
       }

    }
};

面试题 17.12. BiNode

二叉树数据结构TreeNode可用来表示单向链表(其中left置空,right为下一个链表节点)。实现一个方法,把二叉搜索树转换为单向链表,要求值的顺序保持不变,转换操作应是原址的,也就是在原始的二叉搜索树上直接修改。

返回转换后的单向链表的头节点。


链接:https://leetcode-cn.com/problems/binode-lcci
 

/*基本思想:
    方法一:中序遍历思想,新建一个树,按照中序遍历过程连接就好
    方法二:先把左右分别排列好,然后连接,连接的时候注意要找到左和右的头各是什么,左的头是左子树最后的右孩子,右的头是右子树最后的左孩子,连接就好,注意将root的左设置为NULL
*/
/**
 * 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:
    
  void convert(TreeNode* root)
    {
        if(!root)
            return ;
        TreeNode* right = root->right;
        while(right && right->left)
           right = right->left;  
        convert(root->left);
        convert(root->right);     
        TreeNode* left = root->left;
        while(left && left->right)
           left = left->right;
        if(left){
            left->left = NULL;
            left->right = root;
        } 
        if(right){
            root->right = right;
        }
        root->left = NULL;

    }
  
    TreeNode *res = new TreeNode(0);
    TreeNode *result = res;
    void inorder(TreeNode* root)
    {
        if(!root)
            return ;
        inorder(root->left);
        TreeNode*tmp = new TreeNode(root->val);
        res->left = NULL;
        res->right = tmp;
        res = res->right;
        inorder(root->right);
    }
    TreeNode* convertBiNode(TreeNode* root) {
       
        if(!root)
            return NULL;    
        TreeNode* head = root;
        while(head->left)
            head = head->left;  
        convert(root);
        return head;
        /*
        inorder(root);
        return result->right;
        */
    }
};

783. 二叉搜索树结点最小距离

给定一个二叉搜索树的根结点 root,返回树中任意两节点的差的最小值。

链接:https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/

/*基本思想:
    方法一: 利用中序遍历,根据二叉搜索树的特点,中序遍历是一个递增序列,所以求最小的节点差,就是判断相邻两个节点的差最小的,可以在中序遍历的过程中记录每个节点的前一个节点(全局变量记录),然后计算就好.
    方法二: 也是计算找到前一个节点,总体递归思路是,对于一个节点,要比较他和左子树的差和他和右子树的差取最小,并且在他的左子树中找最小和右子树中找最小(递归)。注意比较他和左子树的差的时候,因为二叉搜索树的特点,所以要找到他的左子树的最后的右孩子才是他和左子树的差,同理,他和右子树的差,是他的右子树的最底的左孩子和他的差。
*/
/**
 * 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:
/*
    TreeNode* pre = NULL;
    int min_value = INT_MAX;
    void inorder(TreeNode * root )
    {
        if(!root)
            return ;
        inorder(root->left);
        if(pre)
            min_value = min(min_value, root->val - pre->val);
        pre = root;
        inorder(root->right);
        
    }
    int minDiffInBST(TreeNode* root) {
         
       if(!root)
           return 0;
        inorder(root);
        return  min_value;
    }
    */
    int minDiffInBST(TreeNode* root) {
         
        if(root->left == NULL && root->right == NULL)
            return INT_MAX;
        int left = INT_MAX;
        int right = INT_MAX;
        int leftmin = INT_MAX;
        int rightmin = INT_MAX;
        TreeNode *pre = NULL;
        if(root->left){
            pre = root->left;
            while(pre->right)
                pre = pre->right;
            left = root->val - pre->val;
            leftmin = minDiffInBST(root->left);
        }
        if(root->right){
            pre = root->right;
            while(pre->left)
            {
                pre = pre->left;
            }
            right = pre->val - root->val;
            
            rightmin = minDiffInBST(root->right);
        }
        
        return min(min(left,right), min(leftmin,rightmin));
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值