当前位置: 首页 > article >正文

力扣hot100——二叉树

94. 二叉树的中序遍历

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> stk;
        while (root || stk.size()) {
            while (root) {
                stk.push(root);
                root = root->left;
            }
            auto cur = stk.top();
            stk.pop();
            ans.push_back(cur->val);
            root = cur->right;
        }
        return ans;
    }
};
class Solution {
public:
    int maxDepth(TreeNode* root) {
        auto dfs = [&](this auto&& dfs, TreeNode* root) -> int {
            if (root == NULL) return 0;
            return max(dfs(root->left), dfs(root->right)) + 1;
            };
        return dfs(root);
    }
};

使用栈模拟

中序遍历本质是根在中,从左往右

因此一开始就先往左边找,找不到的情况下,说明可以往右边找了,然后又变成了一个子问题

104. 二叉树的最大深度

class Solution {
public:
    int maxDepth(TreeNode* root) {
        auto dfs = [&](this auto&& dfs, TreeNode* root) -> int {
            if (root == NULL) return 0;
            return max(dfs(root->left), dfs(root->right)) + 1;
            };
        return dfs(root);
    }
};

 经典模拟题

226. 翻转二叉树

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        auto dfs = [](this auto&& dfs, TreeNode* root) -> void {
            if (root == NULL) return;
            TreeNode* tmp = root->left;
            root->left = root->right;
            root->right = tmp;
            dfs(root->left);
            dfs(root->right);
            };
        dfs(root);
        return root;
    }
};
交换指针的时候注意tmp保存

101. 对称二叉树

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        auto dfs = [](this auto&& dfs, TreeNode* p1, TreeNode* p2) -> bool {
            if ((p1 && !p2) || (!p1 && p2) || (p1 && p2 && p1->val != p2->val)) return false;
            if (!p1 && !p2) return true;
            return dfs(p1->left, p2->right) && dfs(p1->right, p2->left);
            };
        return dfs(root->left, root->right);
    }
};

 模拟:分情况考虑即可

543. 二叉树的直径

class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
        int ans = 0;
        auto dfs = [&](this auto&& dfs, TreeNode* root) -> int {
            if (root->left && root->right) {
                int t1 = max(dfs(root->left), 0);
                int t2 = max(dfs(root->right), 0);
                int t = t1 + t2 + 1;
                ans = max(ans, t);
                return max(t1, t2) + 1;
            }
            else if (root->left) {
                int t = max(dfs(root->left), 0) + 1;
                ans = max(ans, t);
                return t;
            }
            else if (root->right) {
                int t = max(dfs(root->right), 0) + 1;
                ans = max(ans, t);
                return t;
            }
            else {
                ans = max(ans, 1);
                return 1;
            }
            };
        dfs(root);
        return ans - 1;
    }
};

 维护以root为根节点(包含在内)的单链最长 

 102. 二叉树的层序遍历

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> v(2000);
        if (root == NULL) return {};
        queue<pair<TreeNode*, int>> q;
        q.push({root, 0});
        while (q.size()) {
            pair<TreeNode*, int> now = q.front();
            q.pop();
            auto u = now.first;
            int dep = now.second;
            v[dep].push_back(u->val);
            if (u->left) {
                q.push({ u->left , dep + 1});
            }
            if (u->right) {
                q.push({ u->right , dep + 1});
            }
        }
        vector<vector<int>> ans;
        for (auto vec : v) {
            if (vec.size()) ans.push_back(vec);
        }
        return ans;
    }
};

 BFS记录深度

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

class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        auto dfs = [&](this auto&& dfs,int l, int r) -> TreeNode* {
            if (l > r) return NULL;
            int mid = (l + r) / 2;
            TreeNode* root = new TreeNode(nums[mid]);
            root->left = dfs(l, mid - 1);
            root->right = dfs(mid + 1, r);
            return root;
            };
        return dfs(0, nums.size() - 1);
    }
};

利用中序遍历的有序性,每次选择中间节点作为根节点,划分子问题

98. 验证二叉搜索树

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        auto dfs = [](this auto&& dfs, TreeNode* root, long long l, long long r) -> bool {
            if (root == NULL) return true;
            if (root->val <= l || root->val >= r) return false;
            return dfs(root->left, l, root->val) && dfs(root->right, root->val, r);
            };
        return dfs(root, LONG_MIN, LONG_MAX);
    }
};

函数表示考虑以 root 为根的子树,判断子树中所有节点的值是否都在 (l,r) 的范围内(注意是开区间)。同时注意开long long

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

class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        // vector<int> v;
        int ans;
        auto dfs = [&](this auto&& dfs, TreeNode* root) -> bool {
            if (root == NULL) return false;
            if (dfs(root->left)) return true;
            k--;
            if (k == 0) {
                ans = root->val;
                return true;
            }
            return dfs(root->right);
            };
        dfs(root);
        return ans;
    }
};

利用平衡二叉树的中序遍历的有序性

199. 二叉树的右视图

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        if (root == NULL) return {};
        vector<int> ans;
        queue<TreeNode*> q;
        q.push(root);
        while (q.size()) {
            vector<TreeNode*> v;
            while (q.size()) {
                v.push_back(q.front());
                q.pop();
            }
            ans.push_back(q.back()->val);
            for (auto root : v) {
                if (root->left)q.push(root->left);
                if (root->right)q.push(root->right);
            }
        }
        return ans;
    }
};

 层序遍历每一层的最右边节点就是答案

114. 二叉树展开为链表

class Solution {
public:
    void flatten(TreeNode* root) {
        TreeNode* dummy = new TreeNode(0);
        TreeNode* cur = dummy;
        auto dfs = [&](this auto&& dfs, TreeNode* root) {
            if (root == NULL) return;
            cur->right = root;
            cur = cur->right;
            TreeNode* pl = root->left;
            TreeNode* pr = root->right;
            cur->left = NULL;
            cur->right = NULL;
            dfs(pl);
            dfs(pr);
            };
        dfs(root);
    }
};

先序遍历模拟

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

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int k = 0;
        map<int, int> mp;
        for (int i = 0; i < inorder.size(); i++)
            mp[inorder[i]] = i;
        auto dfs = [&](this auto&& dfs, int l, int r) -> TreeNode* {
            if (l > r) return NULL;
            TreeNode* root = new TreeNode(preorder[k++]);
            root->left = dfs(l, mp[root->val] - 1);
            root->right = dfs(mp[root->val] + 1, r);
            return root;
            };
        return dfs(0, inorder.size() - 1);
    }
};

只要我们在中序遍历中定位到根节点,那么我们就可以分别知道左子树和右子树中的节点数目。由于同一颗子树的前序遍历和中序遍历的长度显然是相同的,因此我们就可以对应到前序遍历的结果中,对上述形式中的所有左右括号进行定位。

这样以来,我们就知道了左子树的前序遍历和中序遍历结果,以及右子树的前序遍历和中序遍历结果,我们就可以递归地对构造出左子树和右子树,再将这两颗子树接到根节点的左右位置。

每次递归构造的时候,当前先序遍历数组的当前第一个节点一定是当前子树的根节点

437. 路径总和 III

class Solution {
public:
    using ll = long long;
    int pathSum(TreeNode* root, ll targetSum) {
        map<ll, int> mp;
        ll ans = 0;
        mp[0]++;
        auto dfs = [&](this auto&& dfs, TreeNode* root, ll sum) {
            if (root == NULL) return;
            sum += root->val;
            ans += mp[sum - targetSum];
            mp[sum]++;
            dfs(root->left, sum);
            dfs(root->right, sum);
            mp[sum]--;
            };
        dfs(root, 0);
        return ans;
    }
};

哈希,dfs表示从根节点开始统计答案,并且结束后清除对map的影响的贡献

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

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        unordered_map<TreeNode*, int> dep;
        unordered_map<TreeNode*, TreeNode*> f;
        dep[NULL] = 0;
        auto dfs = [&](this auto&& dfs, TreeNode* root, TreeNode* fa) {
            if (root == NULL) return;
            dep[root] = dep[fa] + 1;
            f[root] = fa;
            dfs(root->left, root);
            dfs(root->right, root);
            };
        dfs(root, NULL);
        if (dep[p] < dep[q]) swap(p, q);
        while (dep[p] != dep[q]) {
            p = f[p];
        }
        if (p == q) return p;
        while (p != q) {
            p = f[p];
            q = f[q];
        }
        return p;
    }
};

贪心,先跳到同一层,再往上跳直到相同

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

class Solution {
public:
    int maxPathSum(TreeNode* root) {
        int ans = -1e9;
        auto dfs = [&](this auto&& dfs, TreeNode* root) -> int {
            if (root->left && root->right) {
                int t1 = max(dfs(root->left), 0);
                int t2 = max(dfs(root->right), 0);
                int t = t1 + t2 + root->val;
                ans = max(ans, t);
                return max(t1, t2) + root->val;
            }
            else if (root->left) {
                int t = max(dfs(root->left), 0) + root->val;
                ans = max(ans, t);
                return t;
            }
            else if (root->right) {
                int t = max(dfs(root->right), 0) + root->val;
                ans = max(ans, t);
                return t;
            }
            else {
                ans = max(ans, root->val);
                return root->val;
            }
            };
        dfs(root);
        return ans;
    }
};

贪心,dfs记录从root开始,单链的最大值

注意分类讨论取最大值


http://www.kler.cn/a/464187.html

相关文章:

  • 服务器迁移中心——“工作组迁移”使用指南
  • GitHub Fork 和 Clone 的深度指南:操作解析与 Pull Request 完整流程20241231
  • Halcon 显示异常
  • node内置模块之---path 模块
  • MySQL8安装与卸载
  • C# 在PDF中添加和删除水印注释 (Watermark Annotation)
  • 高效使用AI完成编程项目任务的指南:从需求分析到功能实现
  • 华为OD E卷(100分)45-喊7的次数重排
  • 【网站推荐】IP反查域名实战
  • leetcode 729. 我的日程安排表 I 中等
  • 小程序配置文件 —— 15 页面配置
  • 【2024美国数学建模AB题原文翻译】
  • 基于QT(C++)实现的坦克大战
  • 力扣刷题:栈和队列OJ篇(下)
  • 力扣-数据结构-10【算法学习day.81】
  • 浅谈Beam Search
  • “混合双打”二维数组展平的有效方案(Python)
  • 【SqlSugar雪花ID常见问题】.NET开源ORM框架 SqlSugar 系列
  • requests请求带cookie
  • 深入理解Java Map集合
  • 逻辑回归(Logistic Regression)深度解析
  • 在Swagger(现称为OpenAPI)中各类@api之间的区别
  • k8s系列--docker拉取镜像导入k8s的containerd中
  • HTML——56.表单发送
  • 从零开始学桶排序:Java 示例与优化建议
  • 2025.01.02 一月 | 充分地接受生活本身