Leedcode刷题——4 树

注:以下代码均为c++

数据结构的定义与创建:

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) {}
};
//由扩展先序序列构造二叉树
// 法1:输入数组
vector<int> t = {4,1,-1,-1,6,0,-1,-1,2,-1,-1};  //-1代表空
int i = 0;
void buildTree(TreeNode*& root){  //注意这里必须传引用
    if(t[i] == -1) {
        root = nullptr;
        i++;
    }
    else{
        root = new TreeNode(t[i]);
        i++;
        buildTree(root->left);
        buildTree(root->right);
    }
}
//法2:依次输入字符,其中'#'表示空字符
void buildTree(TreeNode*& root){
    char x;
    cin >> x;
    if(x == '#')
        root = nullptr;
    else{
        root = new TreeNode(x-'0');
        buildTree(root->left);
        buildTree(root->right);
    }
}

1. 验证二叉搜索树

在这里插入图片描述
在这里插入图片描述
思路1:中序遍历有序

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

思路2:先序遍历,判断每个节点取值范围。
在这里插入图片描述

bool dfs(TreeNode *root, long long minv, long long maxv){
    if(root == NULL)
        return true;
    if(root->val < minv || root->val > maxv)
        return false;

    return dfs(root->left, minv, root->val - 1ll)  && dfs(root->right, root->val + 1ll, maxv);
    //1ll:long long类型的1
    //为什么用long long类型?因为节点值可能为int类型边界值,-1或+1会导致溢出。
}

bool isValidBST(TreeNode* root) {
    return dfs(root, INT_MIN, INT_MAX);  //先序,先判断根节点的取值范围,再判断其左右节点的取值范围。
}

2. 二叉树的中序遍历

在这里插入图片描述
在这里插入图片描述

//1.递归:系统帮助我们模拟栈
vector<int> result;
void inOrder(TreeNode* root){
    if(root != NULL){  //注意不要忘记判空
        inOrder(root->left);
        result.push_back(root->val);
        inOrder(root->right);
    }
}

vector<int> inorderTraversal(TreeNode* root) {
    inOrder(root);
    return result;
}
//2.手动写栈
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> stk;
    TreeNode* p = root;
    while(p || stk.size()){
        //1.一路向左入栈
        while(p){
            stk.push(p);
            p = p->left;
        }
        //2.栈顶元素出栈输出
        p = stk.top();
        stk.pop();
        res.push_back(p->val);
        //3.p指向右子树(重复以上步骤)
        p = p->right;
    }
    return res;
}

3. 对称二叉树

在这里插入图片描述
在这里插入图片描述
思路1:递归
在这里插入图片描述

//1. 法1:递归
bool isequal(TreeNode* left, TreeNode* right) {
    if(left && right)
        return left->val == right->val && isequal(left->right, right->left) && isequal(left->left, right->right);
    else{
        if(left == NULL && right == NULL)
            return true;
        else
            return false;
    }
}
bool isSymmetric(TreeNode* root) {
    if(root)
        return isequal(root->left, root->right);
    else
        return true;
}

思路2:迭代
中序遍历,左面:左中右,右面:右中左,
若值全部一一对应返回true,否则返回false

// 2. 法2:迭代
//中序遍历,左面:左中右,右面:右中左,若值全部一一对应返回true,否则返回false
bool isSymmetric(TreeNode* root) {
    if(root == NULL)
        return true;
    stack<TreeNode*> stkleft, stkright;
    TreeNode* l = root->left, *r = root->right;
    while(l || stkleft.size() || r || stkright.size()){
        while(l && r){
            stkleft.push(l);
            l = l->left;
            stkright.push(r);
            r = r->right;
        }

        //如果l和r一个为空一个不为空,返回false
        if(l || r)
            return false;
        //否则比较其数值
        l = stkleft.top();
        stkleft.pop();
        r = stkright.top();
        stkright.pop();
        if(l->val != r->val)
            return false;

        l = l->right;
        r = r->left;
    }
    return true;
}

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

在这里插入图片描述
在这里插入图片描述
思路:
在这里插入图片描述请添加图片描述

//递归的思想。如何查找中序遍历中的root,建立哈希表将中序遍历中每个元素的值与其坐标对应。
unordered_map<int, int> pos;

TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir){
    if(pl > pr)  return NULL;  //注意判断边界
    //1 先序遍历第一个节点为根节点
    int val = preorder[pl];
    TreeNode* root = new TreeNode(val);
    //2 找到根节点在中序遍历的位置,根节点前面为左子树,右面为右子树,递归
    int i = pos[val];
    int left_len = i-1-il;
    root->left = dfs(preorder, inorder, pl+1, pl+1+left_len, il, i-1);
    root->right = dfs(preorder, inorder, pl+1+left_len+1, pr, i+1, ir);
    return root;
}

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    int n = inorder.size();
    for(int i = 0; i < n; i++)
        pos[inorder[i]] = i;  //值=坐标
    return dfs(preorder, inorder, 0, n-1, 0, n-1);
}

5. 二叉树的层序遍历

在这里插入图片描述
在这里插入图片描述

vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> res;  //结果
    if(root == NULL)  return res;

    queue<TreeNode*> q;  //定义队列存储每行的元素
    q.push(root);
    while(q.size()){
        int len = q.size();
        vector<int> level;
        for(int i = 0; i < len; i++){  //分别取每行元素,并把其左右孩子放进队列(即下一行)
            TreeNode* t = q.front();
            q.pop();
            level.push_back(t->val);

            if(t->left)  q.push(t->left);
            if(t->right)  q.push(t->right);
        }
        res.push_back(level);
    }
    return res;
}

6. 二叉树是最近公共祖先

在这里插入图片描述
在这里插入图片描述

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if(root == NULL || root == p || root == q)
        return root;
    TreeNode* left = lowestCommonAncestor(root->left, p, q);
    TreeNode* right = lowestCommonAncestor(root->right, p, q);
    if(left == NULL)  return right;
    if(right == NULL)  return left;
    return root;
}

7. 二叉树的直径

在这里插入图片描述
在这里插入图片描述
思路:
在这里插入图片描述

int ans = 0;
//本质:后序遍历,返回从当前节点向下走的最长路径
int dfs(TreeNode* root){
    if(root == NULL)  return 0;
    int left = dfs(root->left);
    int right = dfs(root->right);
    ans = max(left + right, ans);
    return max(left + 1, right + 1);
}
int diameterOfBinaryTree(TreeNode* root) {
    dfs(root);
    return ans;
}

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

在这里插入图片描述
在这里插入图片描述
思路:此题与上一题类似,递归求解。

int ans = INT_MIN;
//本质:后序遍历,返回从当前节点向下走的最大路径和
int dfs(TreeNode* root){
    if(root == NULL)  return 0;

    int left = dfs(root->left);
    int right = dfs(root->right);
    ans = max(left + right + root->val, ans);

    return max(0, root->val + max(left, right));
}
int maxPathSum(TreeNode* root) {
    dfs(root);
    return ans;
}

9. 二叉搜索树迭代器

在这里插入图片描述
在这里插入图片描述

//本质是一个中序遍历
class BSTIterator {
public:
    stack<TreeNode*> stk;
    BSTIterator(TreeNode* root) {
        while(root){
            stk.push(root);
            root = root->left;
        }
    }

    int next() {
        TreeNode* p = stk.top();
        stk.pop();
        int res = p->val;
        p = p->right;
        while(p){
            stk.push(p);
            p = p->left;
        }
        return res;
    }

    bool hasNext() {
        return !stk.empty();
    }
};
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值