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

每日算法刷题Day75:10.18:leetcode 二叉树14道题,用时3h

九、二叉搜索树

1.套路

1.一般是中序遍历,可以得到有序数组,代码中常用一个pre变量记录前一元素。
2.二叉搜索树满足如下性质:

  • 左子树所有节点的元素值均小于根的元素值;
  • 右子树所有节点的元素值均大于根的元素值。
    3.代码模版:
class Solution {
public:int res = INT_MAX;int pre = INT_MIN / 2; // 为了防止减法溢出void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);// res = min(res, cur->val - pre); // 这一行可以替换pre = cur->val;dfs(cur->right);}int minDiffInBST(TreeNode* root) {dfs(root);return res;}
};
2.题目描述
3.学习经验
1. 700. 二叉搜索树中的搜索(简单)

700. 二叉搜索树中的搜索 - 力扣(LeetCode)

思想

1.给定二叉搜索树(BST)的根节点 root 和一个整数值 val
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
2.根据二叉搜索树性质,得到如下算法:

  • 若 root 为空则返回空节点;
  • 若 val=root.val,则返回 root;
  • 若 val<root.val,递归左子树;
  • 若 val>root.val,递归右子树。
代码
class Solution {
public:TreeNode* searchBST(TreeNode* root, int val) {if (root == nullptr || root->val == val)return root;if (root->val < val)return searchBST(root->right, val);if (root->val > val)return searchBST(root->left, val);return nullptr;}
};
2. 530. 二叉搜索树的最小绝对差(简单,学习)

530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

思想

1.给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
2.简洁写法是中序遍历,同时拿一个pre遍历记录中序遍历数组前一个数

代码

我的代码:

class Solution {
public:typedef pair<int, int> PII;int res = INT_MAX;PII dfs(TreeNode* cur) { // {min,max}if (cur->left == nullptr && cur->right == nullptr) {return {cur->val, cur->val};} else if (cur->left == nullptr && cur->right != nullptr) {PII r = dfs(cur->right);int rMin = r.first, rMax = r.second;res = min(res, rMin - cur->val);return {cur->val, rMax};} else if (cur->left != nullptr && cur->right == nullptr) {PII l = dfs(cur->left);int lMin = l.first, lMax = l.second;res = min(res, cur->val - lMax);return {lMin, cur->val};} else {PII l = dfs(cur->left), r = dfs(cur->right);int rMin = r.first, rMax = r.second;int lMin = l.first, lMax = l.second;res = min(res, cur->val - lMax);res = min(res, rMin - cur->val);return {lMin, rMax};}}int getMinimumDifference(TreeNode* root) {if (root == nullptr)return 0;dfs(root);return res;}
};

中序遍历:

class Solution {
public:int res = INT_MAX;int pre = INT_MIN / 2; // 防止减法溢出(第一次的时候)void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);res = min(res, cur->val - pre);pre = cur->val;dfs(cur->right);}int getMinimumDifference(TreeNode* root) {dfs(root);return res;}
};
3. 783. 二叉搜索树节点最小距离(简单)

783. 二叉搜索树节点最小距离 - 力扣(LeetCode)

思想

1.给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
2.和[[十五.二叉树#2. 530. 二叉搜索树的最小绝对差(简单,学习)]]一样

代码
class Solution {
public:int res = INT_MAX;int pre = INT_MIN / 2;void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);res = min(res, cur->val - pre);pre = cur->val;dfs(cur->right);}int minDiffInBST(TreeNode* root) {dfs(root);return res;}
};
4. 938. 二叉搜索树的范围和(简单)
思想

1.给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和。
2.可以中序遍历,剪枝>high的部分
3.也可以直接依据二叉搜索树的性质决定递归左子树还是右子树,剪枝<low>high的部分

代码

我的代码:

class Solution {
public:int res = 0;void dfs(TreeNode* cur, int low, int high) {if (cur == nullptr)return;dfs(cur->left, low, high);if (cur->val >= low && cur->val <= high)res += cur->val;if (cur->val > high)return; // 剪枝dfs(cur->right, low, high);}int rangeSumBST(TreeNode* root, int low, int high) {dfs(root, low, high);return res;}
};

学习:

class Solution {
public:int rangeSumBST(TreeNode* root, int low, int high) {if (root == nullptr)return 0;int x = root->val;// 剪枝x<lowif (x < low)return rangeSumBST(root->right, low, high);// 剪枝x>highif (x > high)return rangeSumBST(root->left, low, high);return x + rangeSumBST(root->left, low, high) +rangeSumBST(root->right, low, high);}
};
5. 501. 二叉搜索树中的众数(简单)

501. 二叉搜索树中的众数 - 力扣(LeetCode)

思想

1.给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:

  • 结点左子树中所含节点的值 小于等于 当前节点的值
  • 结点右子树中所含节点的值 大于等于 当前节点的值
  • 左子树和右子树都是二叉搜索树
代码
class Solution {
public:map<int, int> valToCnt;vector<int> res;int maxCnt = INT_MIN;void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);++valToCnt[cur->val];if (valToCnt[cur->val] > maxCnt) {res.clear();res.push_back(cur->val);maxCnt = valToCnt[cur->val];} else if (valToCnt[cur->val] == maxCnt) {res.push_back(cur->val);}dfs(cur->right);}vector<int> findMode(TreeNode* root) {dfs(root);return res;}
};
6. 230. 二叉搜索树中第K小的元素(中等)

230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

思想

1.给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 小的元素(从 1 开始计数)。

代码
class Solution {
public:int res;int cnt = 0;void dfs(TreeNode* cur, int k) {if (cur == nullptr)return;dfs(cur->left, k);++cnt;if (cnt == k)res = cur->val;else if (cnt > k)return;dfs(cur->right, k);}int kthSmallest(TreeNode* root, int k) {dfs(root, k);return res;}
};
7. 98. 验证二叉搜索树(中等)

98. 验证二叉搜索树 - 力扣(LeetCode)

思想

1.给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:

  • 节点的左子树只包含 严格小于 当前节点的数。
  • 节点的右子树只包含 严格大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
    2.不用显示数组,还是用一个pre变量
代码
class Solution {
public:vector<int> vec;bool isValidBST(TreeNode* root) {if (root == nullptr)return true;bool isL = isValidBST(root->left);if (!isL)return false;if (!vec.empty() && vec.back() >= root->val)return false;vec.push_back(root->val);bool isR = isValidBST(root->right);if (!isR)return false;return true;}
};

pre变量:

class Solution {
public:typedef long long ll;ll pre = LLONG_MIN;bool isValidBST(TreeNode* root) {if (root == nullptr)return true;if (!isValidBST(root->left))return false;if (pre != LLONG_MIN && pre >= root->val)return false;pre = root->val;if (!isValidBST(root->right))return false;return true;}
};
8. 1305. 两棵二叉搜索树中的所有元素(中等)

1305. 两棵二叉搜索树中的所有元素 - 力扣(LeetCode)

思想

1.给你 root1 和 root2 这两棵二叉搜索树。请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。.

代码
class Solution {
public:vector<int> vec1, vec2;void dfs(TreeNode* cur, vector<int>& vec) {if (cur == nullptr)return;dfs(cur->left, vec);vec.push_back(cur->val);dfs(cur->right, vec);}vector<int> getAllElements(TreeNode* root1, TreeNode* root2) {dfs(root1, vec1);dfs(root2, vec2);vector<int> res;int id1 = 0, id2 = 0, n1 = vec1.size(), n2 = vec2.size();while (id1 < n1 && id2 < n2) {if (vec1[id1] <= vec2[id2]) {res.push_back(vec1[id1]);++id1;} else {res.push_back(vec2[id2]);++id2;}}while (id1 < n1) {res.push_back(vec1[id1]);++id1;}while (id2 < n2) {res.push_back(vec2[id2]);++id2;}return res;}
};
9. 99. 恢复二叉搜索树(中等,学习)

99. 恢复二叉搜索树 - 力扣(LeetCode)

思想

1.给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
2.先搜索,再交换
3.搜索本质是在一个有序数组中找到这两个数,用一个pre变量来记录前一个数,x记录第一个不满足条件的prey记录最后的最小的数(需持续更新)

代码
class Solution {
public:TreeNode *x = nullptr, *y = nullptr, *pre = nullptr;void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);if (pre != nullptr && pre->val > cur->val) {y = cur; // y一直更新到最小的cur->valif (x == nullptr)x = pre; // x为第一次遇见的pre}pre = cur;dfs(cur->right);}void recoverTree(TreeNode* root) {dfs(root);swap(x->val, y->val);}
};
10. 897. 递增顺序搜索树(简单)

897. 递增顺序搜索树 - 力扣(LeetCode)

思想

1.给你一棵二叉搜索树的 root ,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。

代码
class Solution {
public:TreeNode *pre = nullptr, *newRoot = nullptr;void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);if (pre != nullptr) {cur->left = nullptr;pre->right = cur;} else {newRoot = cur;}pre = cur;dfs(cur->right);}TreeNode* increasingBST(TreeNode* root) {dfs(root);return newRoot;}
};
11. 2476. 二叉搜索树最近节点查询(中等)

2476. 二叉搜索树最近节点查询 - 力扣(LeetCode)

思想

1.给你一个 二叉搜索树 的根节点 root ,和一个由正整数组成、长度为 n 的数组 queries 。
请你找出一个长度为 n 的 二维 答案数组 answer ,其中 answer[i] = [mini, maxi] :

  • mini 是树中小于等于 queries[i] 的 最大值 。如果不存在这样的值,则使用 -1 代替。
  • maxi 是树中大于等于 queries[i] 的 最小值 。如果不存在这样的值,则使用 -1 代替。
    返回数组 answer 。
代码
class Solution {
public:vector<int> vec;void dfs(TreeNode* cur) {if (cur == nullptr)return;dfs(cur->left);vec.push_back(cur->val);dfs(cur->right);}vector<vector<int>> closestNodes(TreeNode* root, vector<int>& queries) {dfs(root);int n = vec.size();vector<vector<int>> res;for (auto& x : queries) {int l = 0, r = vec.size() - 1, targetId = vec.size();while (l <= r) {int mid = l + ((r - l) >> 1);if (vec[mid] >= x) {targetId = mid;r = mid - 1;} elsel = mid + 1;}if (targetId == vec.size())res.push_back({vec.back(), -1});else {if (vec[targetId] == x)res.push_back({x, x});else {if (targetId == 0)res.push_back({-1, vec[targetId]});elseres.push_back({vec[targetId - 1], vec[targetId]});}}}return res;}
};
12. 653. 两数之后IV-输入二叉搜索树(简单)

653. 两数之和 IV - 输入二叉搜索树 - 力扣(LeetCode)

思想

1.给定一个二叉搜索树 root 和一个目标结果 k,如果二叉搜索树中存在两个元素且它们的和等于给定的目标结果,则返回 true

代码
class Solution {
public:set<int> st;int pre = INT_MIN;bool res;void dfs(TreeNode* cur, int k) {if (cur == nullptr)return;dfs(cur->left, k);if (st.count(k - cur->val))res = true;st.insert(cur->val);if (res)return;dfs(cur->right, k);}bool findTarget(TreeNode* root, int k) {dfs(root, k);return res;}
};

十、创建二叉树

1.套路

1.大多数题给定数组构造二叉树,本质上是通过查找(可能是二分)获取当前根节点下面,然后左侧数组递归,右侧数组递归,所以递归参数传递当前数组左右边界

2.题目描述
3.学习经验
1. 108. 将有序数组转换为二叉搜索树(简单,学习)

108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

思想

1.给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。
2.用左右边界递归,而不是把左数组和右数组作为参数传递

代码
class Solution {
public:TreeNode* build(vector<int>& nums, int l, int r) {// [l,r]if (r < l)return nullptr;int mid = l + ((r - l) >> 1);// [l,mid),[mid+1,r]return new TreeNode(nums[mid], build(nums, l, mid - 1),build(nums, mid + 1, r));}TreeNode* sortedArrayToBST(vector<int>& nums) {return build(nums, 0, nums.size() - 1);}
};
2. 654. 最大二叉树(中等)

654. 最大二叉树 - 力扣(LeetCode)

思想

1.给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边 的 子数组前缀上 构建左子树。
  3. 递归地在最大值 右边 的 子数组后缀上 构建右子树。
    返回 nums 构建的 最大二叉树 。
代码
class Solution {
public:TreeNode* bulid(vector<int>& nums,int l,int r){// [l,r]if(r<l) return nullptr;int maxId=l;for(int i=l;i<=r;++i){if(nums[i]>nums[maxId]) maxId=i;}// [l,maxId),[maxId+1,r]return new TreeNode(nums[maxId],bulid(nums,l,maxId-1),bulid(nums,maxId+1,r));}TreeNode* constructMaximumBinaryTree(vector<int>& nums) {return bulid(nums,0,nums.size()-1);}
};
3. 998. 最大二叉树II(中等)

998. 最大二叉树 II - 力扣(LeetCode)

思想

1.最大树 定义:一棵树,并满足:其中每个节点的值都大于其子树中的任何其他值。
给你最大树的根节点 root 和一个整数 val 。
就像 之前的问题 那样,给定的树是利用 Construct(a) 例程从列表 aroot = Construct(a))递归地构建的:

  • 如果 a 为空,返回 null 。
  • 否则,令 a[i] 作为 a 的最大元素。创建一个值为 a[i] 的根节点 root 。
  • root 的左子树将被构建为 Construct([a[0], a[1], ..., a[i - 1]]) 。
  • root 的右子树将被构建为 Construct([a[i + 1], a[i + 2], ..., a[a.length - 1]]) 。
  • 返回 root 。
    请注意,题目没有直接给出 a ,只是给出一个根节点 root = Construct(a) 。
    假设 b 是 a 的副本,并在末尾附加值 val。题目数据保证 b 中的值互不相同。
    返回 Construct(b) 。
    2.由例子可以看出:
    a = [2,1,5,4], b = [2,1,5,4,3]
    就是在数组后面插入一个数val,然后来更新树,再由最大树构造性质,只需判断根节点和右子树
代码
class Solution {
public:TreeNode* insertIntoMaxTree(TreeNode* root, int val) {if (root == nullptr)return new TreeNode(val);if (root->val < val) {return new TreeNode(val, root, nullptr);}TreeNode* newR = insertIntoMaxTree(root->right, val);root->right = newR; // 更新右子树return root;}
};
4. 1008. 前序遍历构造二叉搜索树(中等)

1008. 前序遍历构造二叉搜索树 - 力扣(LeetCode)

思想
代码
class Solution {
public:TreeNode* build(vector<int>& preorder, int l, int r) {// [l,r]if (l > r)return nullptr;int tmpL = l, tmpR = r, lEnd = r + 1;// 查找while (tmpL <= tmpR) {int mid = tmpL + ((tmpR - tmpL) >> 1);if (preorder[mid] > preorder[l]) {lEnd = mid;tmpR = mid - 1;} elsetmpL = mid + 1;}// [l+1,lEnd),[lEnd,r]return new TreeNode(preorder[l], build(preorder, l + 1, lEnd - 1),build(preorder, lEnd, r));}TreeNode* bstFromPreorder(vector<int>& preorder) {return build(preorder, 0, preorder.size() - 1);}
};
http://www.dtcms.com/a/500168.html

相关文章:

  • C语言解析json字符串
  • 网站在哪里设置域名站长统计免费下载
  • 街道门户网站的建设思路.net网站模版
  • MyBatis—XML配置
  • Microsoft AI Genius | 用 MCP 解锁实时数据,重新定义交互边界
  • 杨园建设社区网站wordpress digg主题
  • HarmonyOS6 应用升级经验分享
  • 核工业西南建设集团有限公司网站网站管理助手 二级域名
  • 十月通勤小记
  • 贵州住房城乡建设厅官方网站公司的网站
  • 绪论——一文速通
  • 皮卡丘密码
  • 聊城建设局网站做公司官网大概多少钱
  • 教育系统网站cms网站开发完整视频
  • 肇庆免费模板建站logo成品效果图网站
  • 电商网站的支付接入该怎么做呢wordpress静态分页
  • Vue2(一):创建实例、插值表达式、Vue响应式特性、Vue指令、指令修饰符、计算属性
  • 网站建设东莞公司湖南邵阳调整多个风险区
  • 10种常用的进制转换
  • Chainlit+RAG 实战:从前端界面到多模态检索增强生成全流程开发
  • 太原0元网站建设创意网页设计作品
  • 制作网站首先做的是搜素引擎排名优化计费方式
  • Linux系统信息查看:CPU、内存、版本、硬盘使用情况
  • 【CVPR 2025】MaDCoW广角照片任意物体的畸变校正论文笔记
  • 教学单位 网站建设域名大全 二级域名
  • 34部署LNMP架构详细解析
  • 国内跨境电商建站系统北京网站优化企业
  • 【电路·3】化简电路、等效变换、求输入电阻;其实很简单~
  • include″″与includ<>的区别
  • 如何快速提升网站pr网站建站和维护