Leetcode初级算法——树

二叉树的最大深度

给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明:叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
    3
   /  \
 9    20
       /  \
    15    7
返回它的最大深度3 
相关标签:树 深度优先搜索 广度优先搜索 二叉树
#pragma once
#include<algorithm>
#include<queue>
//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 maxDepth(TreeNode* root) {

        /*by myself(深度优先,递归实现)
        if (root == nullptr) {          //遍历到空结点返回
            return 0;
        }

        return std::max(maxDepth(root->left), maxDepth(root->right)) + 1;      //比较每个递归层root的左子树和右子数深度,返回值为 其中的最大深度再加1(因为root本身也是一层,当前递归层最大深度即 max(maxDepth(root->left), maxDepth(root->right)) + 1)

        */


        //(广度优先,使用了队列)
        if (root == nullptr) {        //如果为空树返回0,否则在if (t->left != nullptr)判断时会非法引用
            return 0;
        }

        std::queue<TreeNode*>que;     //队列的作用是存放当前层所有的结点
        int level = 0;                //记录二叉树最大深度(层数)
        
        que.push(root);               //首先将第一层的root节点入队
        while (!que.empty()) {                 //如果队列为空,表示遍历到最深一层,由于最深一层都没有子结点,所以当进入下一层查找时最深一层作为父结点会被出队
            int father_nodes = que.size();     //father_nodes表示这一层结点的个数(也是下一层的父节点的个数)

            while (father_nodes) {             //遍历这一层父结点,查找是否存在子节点,存在就入队,每个父结点查找完毕后将其出队,因此队列里都是下一层的子结点(每次遍历队列中的上层父节点,入队其子结点后删除父结点,队列中的这层子结点将作为下一层的父结点继续遍历查找。直到遍历到最深一层,最深一层的结点没有子结点,所以遍历后没有可入队的子结点,并且删除队列里的这层父结点,因此队列最后为空)
                TreeNode* t = que.front();

                if (t->left != nullptr) {
                    que.push(t->left);
                }
                if (t->right != nullptr) {
                    que.push(t->right);
                }
                que.pop();
                father_nodes--;    //遍历查找后删除一个父结点,father_nodes--
            }

            level++;               //内层while循环结束,表示一层遍历完毕,因此level++
        }

        return level;              //返回最后得到的level,即最大深度

    }
};

验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
示例 :
输入:
    2
   /  \
 1    3
输出: true

输入:
    5
   /  \
 1    4
     /    \
   3       6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
         根节点的值为 5 ,但是其右子节点值为 4 。
相关标签:树 深度优先搜索 二叉搜索树 二叉树
#pragma 
#include<iostream>
#include<stack>
//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 helper(TreeNode* root, long long min, long long max);

    bool isValidBST(TreeNode* root) {

        /* (错误理解) 只考虑到子结点和上一层父结点直间的大小关系,而没有考虑到全部(例如,不仅右子结点应大于其父节点的值,而是整个右子树的所有结点(包括其左子结点)都应该大于其父结点的值)
         * if (root->left != nullptr && root->right != nullptr) {
         *    if (root->val <= root->left->val || root->val >= root->right->val) {
         *        return false;
         *    }
         *
         *    if (!isValidBST(root->left)) {
         *        return false;
         *    }      
         *    if (!isValidBST(root->right)) {
         *        return false;
         *    }
         * }
         * return true;
         */
        

        /*(递归)
        return helper(root, LONG_MIN, LONG_MAX);

        */


        //(中序遍历,迭代,利用栈)
        std::stack<TreeNode*>stk;         //使用栈来模拟中序遍历的过程

        long long min = LONG_MIN;         //定义一个最小值(如果满足二叉搜索树再结合中序遍历特点,可知中序遍历后的所以结点是从小到大排列的。所以只要按照中序遍历对所有结点进行比较,如果满足从小到大的次序则是二叉搜索树)
                                          
        while (!stk.empty() || root != nullptr) {     //初始时,栈是空的,root!=nullptr(非空树);中序遍历过程中,栈不是空的,root==nullptr或者root!=nullptr(即右结点可能是空也可能不是);遍历结束时,栈是空的,root==nullptr(所有应该为||而不是&&,否则进入不了循环,中间遍历过程也可能突然退出)
            while (root != nullptr) {     //只要left存在就一直找left,直到nullptr
                stk.push(root);           //左要保留在栈中
                root = root->left;
            }

            root = stk.top();             //当root==nullptr(即left_r->left==nulltr),弹出left_r,root=left_r
            stk.pop();
            if (root->val <= min) {       //此时的root(left_r)即 中,将 中 与min比较,如果 中>=min,则说明不是二叉搜索树(不管前序、中序、后序遍历,所有结点都会有作为 中,比如前序遍历第一次遍历到该结点就是 中,中序遍历第二次遍历到该结点就是 中,后续遍历第三次遍历到该结点就是 中。所有所有结点都会成为中别遍历到,三种遍历只是说最终所有结点作为 中 被遍历到的顺序不同而已)
                return false;
            }
            min = root->val;              //min被设置为被遍历到的结点值,接着与下一个 中 比较
            root = root->right;           //找完了左,中,找右(以右作为新的子树root,继续不断找左)  
        }

        return true;                      //如果完整中序遍历完,说明该树就是二叉搜索树
    }
};

bool Solution::helper(TreeNode* root, long long min, long long max) {    //自己设计一个递归函数,增加每个结点值范围的参数(min,max)
    if (root == nullptr) {        //遍历到空结点,返回true
        return true;
    }

    if (root->val <= min || root->val >= max) {    //该结点不在范围内,即不满足二叉搜索树,返回false
        return false;
    }

    return helper(root->left, min, root->val) && helper(root->right, root->val, max);     //对左右子树进行递归,只有在都返回true时才满足二叉搜索树的条件(这里对左子树root的范围为(min, root->val),对左子树root的范围为(root->val, max)。min和max在动态变化,即被覆盖,最终的目的就是要满足,对于左子树而言:左子树上的所有结点都应该小于这个左子树root,虽然存在树里面的子树,不管是外层树还是内层子树,只要该结点在其树上,既要小于外层树root,也要小于内存子树的root)


}

对称二叉树

给定一个二叉树,检查它是否是镜像对称的。
例如:
二叉树 [1,2,2,3,4,4,3] 是对称的
         1
       /    \
     2      2
   /    \  /    \
 3     4 4     3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的
      1
     /   \
    2    2
      \      \
        3     3
进阶:
你可以运用递归和迭代两种方法解决这个问题吗?
相关标签:树 深度优先搜索 广度优先搜索 二叉树
#pragma once
#include<deque>
#include<queue>
#include<stack>
#include<vector>

//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 is_hui_wen(std::deque<TreeNode*> DQ_t);  //验证双端队列DQ_t中存储的结点是否构成回文(DQ_t中存储二叉树当前层的结点)
    bool is_hui_wen(std::vector<TreeNode*> vec);  //验证双端队列DQ_t中存储的结点是否构成回文(vec中存储二叉树当前层的结点的值)
    bool compare(TreeNode* t1, TreeNode* t2);     //比较对称位置t1,t2结点是否都存在,如果存在是否值相同
    bool check(TreeNode* t1, TreeNode* t2);       //官方代码简化版

    bool isSymmetric(TreeNode* root) {
        /*by myself(层序遍历,回文判断,有点暴力味)
        
        std::deque<TreeNode*>DQ;
        std::deque<TreeNode*>DQ_t;
        TreeNode* t = new TreeNode(-1);           //假设所有结点值都>0,在这里t代指一个空结点,起到占位作用(埋了个内存泄露的伏笔)
        

        DQ.push_back(root);
        DQ_t.push_back(root);

        while (!DQ.empty()) {       //中序遍历
            if (!is_hui_wen(DQ_t)) {              //如果当前层的结点按从左到右顺序不构成回文,则直接返回false
                return false;
            }
            DQ_t.clear();                         //清空双端队列DQ_t,即清空上一层结点,准备存入当前层结点

            int level_nodes = DQ.size();          //双端队列DQ_t中存储着上一层结点,寻找当前层结点是根据上一层结点进行
            while (level_nodes) {                 //根据上一层记录的结点,寻找下一层结点
                root = DQ.front();

                if (root->left != nullptr) {      //以上一层结点为root,如果存在左右结点,则插入到DQ和DQ_t中(每查找完DQ中存储的当前root结点,如果存在其左右则插入,插入完删除该root,继续查找DQ中下一个root)
                    DQ.push_back(root->left);    
                    DQ_t.push_back(root->left);
                }
                else {                           
                    DQ_t.push_back(t);            //如果root不存在left或者right,对于DQ是不插入的,但是对于DQ_t需要插入一个t
                }
                if (root->right != nullptr) {
                    DQ.push_back(root->right);
                    DQ_t.push_back(root->right);
                }
                else {
                    DQ_t.push_back(t);
                }

                DQ.pop_front();
                level_nodes--;       //每查找完上一层一个结点,level_nodes--,当level_nodes==0,表示上一层结点查找遍历完毕
            }
        }

        return true;
        */


        /*by myself(层序遍历,回文判断,简单优化:用queue和vector代替deque)
        
        std::queue<TreeNode*>Q;
        std::vector<TreeNode*>vec;


        Q.push(root);
        vec.push_back(root);

        while (!Q.empty()) {        //中序遍历
            if (!is_hui_wen(vec)) {               //如果当前层的结点按从左到右顺序不构成回文,则直接返回false
                return false;
            }
            vec.clear();                          //清空vec,即清空上一层结点,准备存入当前层结点

            int level_nodes = Q.size();           //队列Q中存储着上一层结点,寻找当前层结点是根据上一层结点进行
            while (level_nodes) {                 //根据上一层记录的结点,寻找下一层结点
                root = Q.front();

                if (root->left != nullptr) {      //以上一层结点为root,如果存在左右结点,则插入到Q和vec中(每查找完DQ中存储的当前root结点,如果存在其左右则插入,插入完删除该root,继续查找Q中下一个root)
                    Q.push(root->left);
                    vec.push_back(root->left);
                }
                else {
                    vec.push_back(nullptr);       //如果root不存在left或者right,对于Q是不插入的,但是对于vec需要插入一个nullptr(nullptr起到占位作用)
                }
                if (root->right != nullptr) {
                    Q.push(root->right);
                    vec.push_back(root->right);
                }
                else {
                    vec.push_back(nullptr);
                }

                Q.pop();
                level_nodes--;                    //每查找完上一层一个结点,level_nodes--,当level_nodes==0,表示上一层结点查找遍历完毕
            }
        }

        return true;

        */


        /*by myself(递归)
        
        return compare(root->left, root->right);

        */


        /*(递归,代码排放简明,逻辑性更强)
        
        return check(root->left, root->right);

        */

        
        /*by myself(迭代,栈实现)
        
        std::stack<TreeNode*>stk;   
        stk.push(root);
        stk.push(root);
        TreeNode* t1 =root->left;
        TreeNode* t2 = root->right;

        while (!stk.empty()) {    

            if (t1 == nullptr && t2 != nullptr || t1 != nullptr && t2 == nullptr) {        //1.在新的一轮开始时要判断 "t1父结点的right,t2父结点的left"作为新的root的两个结点(新一轮初始时判断)
                return false;
            }
            while (t1 != nullptr && t2 != nullptr) {      //从当前树,不断向下查找比较left和right结点,无非三种情况:(1)t1,t2都为nullptr,返回flase; (2)t1,t2只有一个为nullptr,返回false; (3)t1,t2都不为nullptr,值相对返回true,否则返回false;
                if (t1->val != t2->val) {                 //能正常从循环中出来,说明t1==nullptr,t2==nullptr,否则都会返回false。
                    return false;
                }
                stk.push(t1);
                stk.push(t2);
                t1 = t1->left;              //不断查找判断 左和右 结点
                t2 = t2->right;
                if (t1 == nullptr && t2 != nullptr || t1 != nullptr && t2 == nullptr) {   //2.在向下查找比较 左和右结点 时要判断(过程中判断)
                    return false;
                }
            }

            t2 = stk.top()->left;        //当t1==nullptr,t2==nullptr,此应该继续查找 "t1父结点的right,t2父结点的left ",并且t1,t2各自的父结点作为root的俩颗子树,继续查找比较 左和右 结点
            stk.pop();                   //注:由于是栈的缘故,开始是t1、t2入栈,此时应该以t2、t1顺序接收出栈值(stk.top()即他们的父结点)
            t1 = stk.top()->right;
            stk.pop();
            
        }

        return true;

        */

          
        //(迭代,队列实现)
        std::queue<TreeNode*>Q;        

        Q.push(root->left);
        Q.push(root->right);
        while (!Q.empty()) {               //结合广度优先遍历理解,只不过这里是同时处理俩组(左右,右左),但也是一层一层处理
            TreeNode* t1 = Q.front();      //和广度优先遍历类似,当t1,t2作为父结点的时候应移除队列,并且在此时进行比较
            Q.pop();
            TreeNode* t2 = Q.front();
            Q.pop();

            if (t1 == nullptr && t2 == nullptr) {
                continue;
            }
            if (t1 == nullptr || t2 == nullptr || t1->val != t2->val) {
                return false;
            }

            Q.push(t1->left);            //对于两个位置对称的父结点t1,t2来说:t1->left和t2->right;t1->right和t2->left是两组位置对称的子结点,将他们加入队列
            Q.push(t2->right);

            Q.push(t1->right);            
            Q.push(t2->left);
        }

        return true;
    }
};


bool Solution::is_hui_wen(std::deque<TreeNode*> DQ_t) {    //判断是否为构成回文
    while (!DQ_t.empty()) {
        TreeNode* first = DQ_t.front();
        TreeNode* last = DQ_t.back();
        if (first->val != last->val) {
            return false;
        }

        if (DQ_t.size()>1) {
            DQ_t.pop_front();
            DQ_t.pop_back();
        }
        else {
            DQ_t.pop_front();
        }
    }
    
    return true;
}

bool Solution::is_hui_wen(std::vector<TreeNode*>vec) {    //判断是否为构成回文
    auto first = vec.begin();
    auto last = vec.end()-1;

    while (first < last) {
        if ((*first != nullptr && *last != nullptr) && (*first)->val != (*last)->val) {            //first、last是有效的结点则比较值,不等则不构成回文,返回false
            return false;
        }
        if ((*first == nullptr && *last != nullptr) || (*first != nullptr && *last == nullptr)) {  //first、last其中一个为有效结点,一个为无效结点,则肯定不构成回文,返回false
            return false;                                                                          //满足条件情况:first、last都为无效结点 或者 都为有效结点且值相等
        }

        first++;      
        last--;
    }

    return true;
}


bool Solution::compare(TreeNode* t1, TreeNode* t2) {     //t1,t2两个结点是对称结点(位置对称)
    if (t1 != nullptr && t2 != nullptr) {                //如果是对称二叉树,最起码每个结点都有一个与之位置对称的结点
        if (t1->val == t2->val) {                        //每个结点不仅要有位置上对称的结点,而且结点值要相等。在满足这样的条件下才有必要继续递归比较下去
            if (!compare(t1->left, t2->right)) {    //可知t1和t2是两个位置对称结点(从root开始推就可知,t1处于root的左,t2处于root的右),所以接下来要比较t1,t2这俩个结点的子结点也必须对称,所以t1->left对应的是t2->right,t1->right对应的是t2->left。(一个左一个右才呈对称位置)
                return false;                       //如果compare函数返回false则直接向上一层返回false
            }
            if (!compare(t1->right, t2->left)) {
                return false;
            }
        }
        else {                                           //如果对称位置上两个结点值不等,返回false
            return false;
        }
        
    }

    if ((t1 == nullptr && t2 != nullptr) || (t1 != nullptr && t2 == nullptr)) {   //如果一个结点连对称位置上都不存在相应对称结点,肯定不满足对称二叉树,直接返回false
        return false;
    }

    return true;       //上面俩个if如果都不满足,说明t1,t2都为nullptr,说明这一递归层的对应位置都是空结点,直接返回上一层,所以返回true
}

bool Solution::check(TreeNode* t1, TreeNode* t2) {      //官方代码简化版,无非三种情况: (1)t1,t2都为nullptr,返回flase; (2)t1,t2只有一个为nullptr,返回false; (3)t1,t2都不为nullptr,值相对返回true,否则返回false;
                                              //我是按(3)(2)(1)顺序写,(3)(2)为俩个if,剩下自然是(1),放在return。官方an(1)(2)(3),先写明(1)(2)俩代码量最少的,剩下情况自然就是(3),(3)代码量最多,放在return,省去了冗余的判断,因为(1)(2)判断完,剩下肯定是(3)这种情况不用再次判断
    if (t1 == nullptr && t2 == nullptr) {     
        return true;
    }
    if (t1 == nullptr || t2 == nullptr) {     //根据上面判断知道,到这里说明t1,t2不可能都为nullptr,所以判断t1,t2是否只有一个为nullptr时,只需要判断t1==nullptr或t2==nullptr就行,满足就返回flase
        return false;
    }

    return (t1->val == t2->val) && check(t1->left, t2->right) && check(t1->right, t2->left);  //因为经过了(1)(2)判断这里默认就是(3)成立,即t1,t2都不为空。利用了&&的特点,先把(t1->val == t2->val)放前面,满足才会判断后来俩个函数,即继续递归,否则直接跳过后面俩个函数返回flase,正好和(3)对上。
}

二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7],
         3
       /   \
     9    20
           /    \
        15      7
返回其层序遍历结果:
[
  [3],
  [9,20],
  [15,7]
]
相关标签:树 广度优先搜索 二叉树
#pragma once
#include<vector>
#include<queue>

using std::vector;

//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:
    vector<vector<int>>& helper(TreeNode* root, int level, vector<vector<int>>& vec);

    vector<vector<int>> levelOrder(TreeNode* root) {

        /*by myself(队列实现)
        std::queue<TreeNode*>Q;
        vector<vector<int>>vec;     
        int level = 0;

        if (root == nullptr) {        //root为空要返回,否则下面语句 if(t->left != nullptr) 非法引用
            return vec;
        }

        Q.push(root);
        while (!Q.empty()) {
            int nodes_level = Q.size();
            vec.resize(level + 1);             //vector<vector<int>>vec;这样定义的vec没有分配空间,不能够直接vec[1]!!!。两种方法:(1)vec.resize(level + 1) (2)vec.push_back(vector <int> ())。emmm,后面这种更加C++

            while (nodes_level) {
                TreeNode* t = Q.front();
                vec[level].push_back(t->val); //每一层对应二维数组vec的每一个元素(即一维数组),这里遍历每一层结点时,只需要将其插入其所在层对应的一维数组中
                Q.pop();

                if (t->left != nullptr) {
                    Q.push(t->left);
                }
                if (t->right != nullptr) {
                    Q.push(t->right);
                }

                nodes_level--;      
            }

            level++;
        }

        return vec;

        */


        //by myself(递归)
        vector<vector<int>>vec;
        return helper(root, 0, vec);
    }
};

vector<vector<int>>& Solution::helper(TreeNode* root, int level, vector<vector<int>>& vec) { //因为要层序遍历,所有这把结点所在层数level作为参数传递,传递vec参数目的为了传引用,以免因递归调用而导致多次构造数组带来的浪费
    if (root == nullptr) {
        return vec;
    }

    if (level + 1 > vec.size()) {      //要判断在该递归层level时,vec.size()如果小于level+1,则说明该层对应的一维数组空间还不存在,所以要对vec进行扩容
        vec.resize(level + 1);
    }
    vec[level].push_back(root->val);   //采用先序遍历,将结点插入其所在层对应的一维数组中(直接插入后面就行,不管是先序、中序、后续遍历,其本质都是从左往右遍历)

    helper(root->left, level + 1, vec);  
    helper(root->right, level + 1, vec);

    return vec;
}

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

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
示例 1:

输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

输入:nums = [1,3]
输出:[3,1]
解释:[1,3] 和 [3,1] 都是高度平衡二叉搜索树。
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 按 严格递增 顺序排列
相关标签:树 二叉搜索树 数组 分治 二叉树
#pragma once
#include<vector>

using std::vector;

//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* helper(const std::vector<int>& vec, int left, int right);

    TreeNode* sortedArrayToBST(vector<int>& nums) {

        /*(错误实例)
        //泪目,想用贪心,贪错了。。  (原本思路:首先确顶root(在这里是3,即数组中间元素),如果vec.size()>3,那么再确定root->left,root->right(在这里分别为2、5,left即数组中间元素的前一个,right为数组最后一个),root->left之前的全部接在root->left结点左边,root到root->right之前的结点,全部接在root->right左边。
        //这样构造出的树虽然满足搜索树,但是"不是完全的平衡二叉树(AVL)",AVL对所有节点作为root的子树时也都必须满足AVL!!!(即每个节点的左右两个子树的高度差的绝对值不超过 1)
                                                                //        输出结果          预期结果         数组vec={0,1,2,3,4,5}
        int root_index = nums.size() / 2;                       //           3                  3
        TreeNode* root = new TreeNode(nums[root_index]);        //          / \               /   \
                                                                //         2   5            1       5
        TreeNode* t = root;                                     //        /   /            / \     /
        for (int i = root_index - 1; i >= 0; i--) {             //       1   4            0   2   4
            TreeNode* p = new TreeNode(nums[i]);                //      /   
            t->left = p;                                        //     0
            t = p;
        }

        if (root_index != nums.size() - 1) {
            TreeNode* p = new TreeNode(nums[nums.size() - 1]);
            root->right = p;

            t = p;
            for (int i = nums.size() - 2; i > root_index; i--) {
                TreeNode* p = new TreeNode(nums[i]);
                t->left = p;
                t = p;
            }
        }

        return root;

        */


        //(中序遍历,递归)
        return helper(nums, 0, nums.size() - 1);       //二叉搜索树的中序遍历是升序序列,题目给定的数组是按照升序排序的有序数组,因此可以确保数组是二叉搜索树的中序遍历序列。
                                                       //注:就算给定二叉搜索树的中序遍历,也不可以唯一地确定二叉搜索树,这里再子树结点为偶数数时,总是选择中间位置左边作为root,中间位置右边也可以,如果这两种可能再在每一个递归层(也就是当前层子树)交错选择,会导致多种不同结果。



    }
};

TreeNode* Solution::helper(const std::vector<int>& vec, int left, int right) {
    if (left > right) {
        return nullptr;
    }

    int mid = (right + left) / 2;

    TreeNode* root = new TreeNode(vec[mid]);       //总选择中间位置(奇个)或者左边(偶个)作为该所在层子树的root。确定平衡二叉搜索树的根节点之后,其余的数字分别位于平衡二叉搜索树的左子树和右子树中,左子树和右子树分别也是平衡二叉搜索树,因此可以通过递归的方式创建平衡二叉搜索树。
                                                   //为什么这么建树一定能保证是「平衡」的呢? 简单脑部理解就是:这样递归也是一直二分下去,分一半结点给左边以left为根结点建立左子树,分一半给右边以right为根结点建立右子树。按递归走只是先建立左再建立右,但是每一层的左右子树在每一层都早已经二分好了,最后得到的树是平衡二叉树
    root->left = helper(vec, left, mid - 1);      
    root->right = helper(vec, mid + 1, right);

    return root;
}




全部评论

相关推荐

点赞 评论 收藏
转发
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务