二叉树

二叉树

94.二叉树的中序遍历

image

image

方案一:递归算法

中序遍历顺序左根右

/**
 * 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 inorder(TreeNode *d,vector<int>&a){//d是当前根节点,a是答案返回数组
        if(!d){#d为空节点
            return;
        }
        inorder(d->left,a);//左
        a.push_back(d->val);//根
        inorder(d->right,a);//右
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>ans;
        inorder(root,ans);
        return ans;
    }
};

104.二叉树的最大深度

image

/**
 * 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 calculate_height(TreeNode*a){
        if(!a){//空节点
            return 0;
        }
        return 1+max(calculate_height(a->left),calculate_height(a->right));//递归
    }
    int maxDepth(TreeNode* root) {
        return calculate_height(root);
    }
};

226.翻转二叉树

image

递归思想:先递归翻转左右子树,再交换左右子树,记得保存左右指针副本防止被覆盖(交换时左右指针不变)。

/**
 * 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* invertTree(TreeNode* root) {
      if(!root){
        return nullptr;
      }
      TreeNode*l=root->left;
      TreeNode*r=root->right;
      root->left=invertTree(r);
      root->right=invertTree(l);
      return root;
    }
};

101.对称二叉树

image

递归:

/**
 * 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 ismirror(TreeNode* a, TreeNode* b) { // 判断a和b两个子树是否对称
        if (!a && !b) { // a和b两个都是空节点->一定对称
            return true;
        }
        if (!a || !b) { // a和b之间有一个是空节点
            return false;
        }
        //a与b都是非空结点
        return (a->val==b->val)&&ismirror(a->left,b->right)&&ismirror(a->right,b->left);
    }
    bool isSymmetric(TreeNode* root) {
        if (!root) {
            return true;
        }
        return ismirror(root->left,root->right);//看左右子树是否镜像对称
    }
};

迭代:

用一个队列存放

 

/**
 * 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 check(TreeNode* a, TreeNode* b) { 
     //迭代
     queue<TreeNode*>q;
     q.push(a);
     q.push(b);
while(!q.empty()){
    TreeNode*x=q.front();q.pop();
    TreeNode*y=q.front();q.pop();
    if(!x&&!y)continue;//都是空节点也相等可以跳下一步
    if((!x||!y)||(x->val!=y->val))return false;//不相等的情况:1.一个空一个非空 2.如果是都非空则值不相等时不相等
    //对称:左枝左和右枝右,左枝右和右枝左
    q.push(x->left);
    q.push(y->right);
    q.push(x->right);
    q.push(y->left);
}
     return true;//只用当循环结束时才知道完全对称
    }
    bool isSymmetric(TreeNode* root) {
        return check(root,root);
    }
};

543.二叉树的直径

image 

/**
 * 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 {
private:
int ans;
int depth(TreeNode*root){
    //从下往上计算深度,空节点的深度0
    if(root==nullptr)return 0;
    int l=depth(root->left);
    int r=depth(root->right);
    ans=max(ans,l+r+1);//一个节点跨两边算以这个节点为根的的边的总和。
    return max(l,r)+1;//当前的结点高度

}
public:
    int diameterOfBinaryTree(TreeNode* root) {
    ans=1;
    depth(root);
    return ans-1;
    }
};

102.二叉树的层序遍历

image

/**
 * 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>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        if (!root) {
            return ans;
        }
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            int s = q.size();
            ans.push_back(vector<int>()); // 先在二维数组内放入一个一维数组
            for (int i = 1; i <= s; i++) {//当前层
                TreeNode* a = q.front();
                q.pop();
                ans.back().push_back(a->val);
                if (a->left)
                    q.push(a->left);
                if (a->right)
                    q.push(a->right);
            }
        }
        return ans;
    }
};

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

image

 

/**
 * 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*
    sorttree(vector<int>& nums, int low,
             int high) { // 对数组下标low->high的元素进行二叉搜索树转换
      
        if (low > high) {
            return nullptr;
        }  
        int mid = (low + high) / 2;
        TreeNode* root = new TreeNode(nums[mid]); // 二叉树根节点

        //根节点左右
        root->left = sorttree(nums, low, mid - 1);
        root->right = sorttree(nums, mid+1, high);
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return sorttree(nums, 0, nums.size() - 1);
    }
};

98.验证二叉搜索树

image

下面这个方法错误的原因是:

例如左儿子<根且左边是二叉搜索树并不能保证左子树上点全小于根。

root->left->val < root->val && isValidBST(root->left)

/**
 * 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 isValidBST(TreeNode* root) {
        if (!root) {
            return true;
        }
        TreeNode* l;
        TreeNode* r;
        if (!root->left && !root->right) {
            return true;
        } else if (!root->right) {
            if (root->left->val < root->val && isValidBST(root->left)) {
                return true;
            }
            return false;
        } else if (!root->left) {
            if (root->right->val > root->val && isValidBST(root->right)) {
                return true;
            }
            return false;
        } else {
            if (root->right->val > root->val && isValidBST(root->right) &&
                root->left->val < root->val && isValidBST(root->left)) {
                return true;
            }
            return false;
        }
    }
};

 正确方法与第108题一样,二分

按照取值二分:最小~最大

/**
 * 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 checker(TreeNode*root,long long lower,long long upper){//lower下界,upper上界
if(!root){
    return true;//空节点
}
if(lower>=root->val||upper<=root->val){
    return false;
}
return checker(root->left,lower,root->val)&&checker(root->right,root->val,upper);
    }
    bool isValidBST(TreeNode* root) {
  return     checker(root,LONG_MIN,LONG_MAX);//系统默认最大最小值LONG_MIN,LONG_MAX
    }
};

230.二叉搜索树中第k小的元素

image

/**
 * 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 zx(TreeNode*root,vector<int>&v){
    if(!root){
        return ;
    }
    zx(root->left,v);
    v.push_back(root->val);
    zx(root->right,v);
}
    int kthSmallest(TreeNode* root, int k) {
        vector<int>v;
        zx(root,v);
        sort(v.begin(),v.end());
        return v[k-1];
    }
};

利用中序遍历,将所有点放入数组,再排序

199.二叉树的右视图

image

思路:层序遍历

/**
 * 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<int> rightSideView(TreeNode* root) {
        vector<int> ans;
        int maxdepth = -1;
        // 思路:利用层序遍历每一层遍历的最后一个是右视图内的点。
        unordered_map<int, int> mp; // 层高和本层最后的一个元素
        queue<TreeNode*> qt;        // 树结点
        queue<int> qd;              // 树深
        qt.push(root);
        qd.push(0);
        while (!qt.empty()) {
            TreeNode* node = qt.front();
            int depth = qd.front();//弹出一个点需要弹出他的对应高度
            qt.pop();
            qd.pop();
            if (node) {

                mp[depth] = node->val;
                maxdepth = max(maxdepth, depth);
                qt.push(node->left);
                qt.push(node->right);
                qd.push(depth + 1); // 左子树深
                qd.push(depth + 1); // 右子树深
            }
        }
        for (int i = 0; i <= maxdepth; i++) {
            ans.push_back(mp[i]);
        }
        return ans;
    }
};

114.二叉树展开为链表

image

/**
 * 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 {
private:
    queue<TreeNode*> q;

public:
    void xx(TreeNode* root) {
        if (!root)
            return;
        q.push(root);    // 先序遍历:根
        xx(root->left);  // 先序遍历:左
        xx(root->right); // 先序遍历:右
    }

    void flatten(TreeNode* root) {
        if (!root){
        return;
        }
        xx(root);
        root = q.front();
        q.pop();
        TreeNode* curr = root;
        while (!q.empty()) {
            curr->left = nullptr;
            curr->right = q.front();
            q.pop();
            curr = curr->right;
        }
    }
};

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

image

/**
 * 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 {
    private:unordered_map<int,int>index;//因为要根据中序遍历定位,高效定位用哈希表,index[元素值]=中序遍历的位置的下标
public:
    TreeNode*mybuildtree(vector<int>& preorder, vector<int>& inorder,int preleft,int preright,int inorderleft,int inorderright){
//vector<int>& preorder前序遍历, vector<int>& inorder中序遍历,int preleft前序的左端点,int preright前序的右端点,int inorderleft中序左端点,int inorderright中序右端点
if(preleft>preright){
    return nullptr;
}
int treeroot=preorder[preleft];//前序遍历中第一个点是根,该变量存根值
TreeNode*root=new TreeNode(treeroot);
int p=index[treeroot];//中序遍历,找到根节点在中序遍历中位置由此确定左右子树大小
int ltree=p-inorderleft;//左子树大小(由中序遍历确定,左根右)
//递归左子树,在前序遍历中排除根后左子树从preleft+1到preleft+ltree,在中序遍历中左子树从inorderleft到左子树中最后一个点(中序遍历中根的前一个点p-1)
root->left=mybuildtree(preorder,inorder,preleft+1,preleft+ltree,inorderleft,p-1);//递归构建左子树
//递归构建右子树,排除根后右子树从preleft+1+ltree到preright,在中序遍历中右子树从p+1到右子树中最后一个点inorderright
root->right=mybuildtree(preorder,inorder,preleft+1+ltree,preright,p+1,inorderright);//递归去构建右子树
return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n=preorder.size();
        for(int i=0;i<n;i++){
            index[inorder[i]]=i;
        }
        return mybuildtree(preorder,inorder,0,n-1,0,n-1);
    }
};

236.二叉树的最近公共祖先

image

 

/**
 * 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 {
private:
TreeNode*ans;
public:
bool dfs(TreeNode*root,TreeNode* p, TreeNode* q){//只有当root为根的树中同时包含p,q时才返回true
    if(!root){//root是空的时候就不可能包含pq
        return false;
    }
    bool lson=dfs(root->left,p,q);//左子树是否同时含p和q
    bool rson=dfs(root->right,p,q);//右子树是否同时含有p与q
    if((lson&&rson)||((lson||rson)&&((root->val==p->val)||(root->val==q->val)))){
        //root可能是答案的情况:1.左右子树同时包含p与q  2.左右子树中有包含p与q的,且根恰好就是p与q中的一个
        ans=root;
    }
return lson||rson||(root->val==p->val)||(root->val==q->val);
}
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        dfs(root,p,q);
        return ans;
    }
};

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

image

/**
 * 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 {
private:
    int ans = INT_MIN;
    int js(TreeNode* root) {
        if (!root) {
            return 0;
        }
        int leftgain = max(0, js(root->left));//左子树最大权值和
        int rightgain = max(0, js(root->right));//右子树最大权值和
        int pathval = root->val + leftgain + rightgain;//经过root结点的路径中的最大权值和
        ans = max(ans, pathval);
        return root->val+max(leftgain,rightgain);//到当前结点时的最大权值和
    }

public:
    int maxPathSum(TreeNode* root) {
        js(root);
        return ans;
    }
};

 

437.路径总和III

image

image

/**
 * 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 rootsum(TreeNode*root,long long targetSum){
        if(!root){
            return 0;
        }
        //利用ret来统计能凑到targetsum的路径数
        int ret=0;
        if(root->val==targetSum){//当前结点值是targetsum
            ret++;
        }
        //包含根节点的左子树或右子树凑到targetsum
        ret+=rootsum(root->left,targetSum-root->val);
        ret+=rootsum(root->right,targetSum-root->val);
        return ret;
    }
    int pathSum(TreeNode* root, int targetSum) {
        if(!root){
            return 0;
        }
      int ret=rootsum(root,targetSum);//计算包含root结点的路径和为targetsum的总路径数量。
      ret+=pathSum(root->left,targetSum);//左子树凑到targetSum
      ret+=pathSum(root->right,targetSum);//右子树凑到targetSum
      return ret;
    }
};

 

posted @ 2025-12-14 23:31  Annaprincess  阅读(8)  评论(0)    收藏  举报