【算法篇】二叉树类(2)(笔记)

ops/2024/9/29 3:31:28/

目录

一、Leetcode 题目

1. 左叶子之和

(1)迭代法

(2)递归法

2. 找左下角的值

(1)广度优先算法

(2)递归法

3. 路径总和

(1)递归法

(2)迭代法

4. 从中序与后序遍历序列构造>二叉

5. 从前序与中序遍历序列构造>二叉

6. 最大>二叉

树>二叉-toc" style="margin-left:40px;">7. 合并>二叉

(1)递归法

(2)迭代法

8. 二叉搜索中的搜索

(1)递归法

(2)迭代法

9. 验证二叉搜索

(1)递归法

(2)迭代法

10. 二叉搜索的最小绝对差

11. 二叉搜索中的众数

(1)递归法

(2)迭代法


一、Leetcode 题目

1. 左叶子之和

404. 左叶子之和 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/sum-of-left-leaves/description/

        给定>二叉的根节点 root ,返回所有左叶子之和。

示例 1:
​​​​​​​输入: root = [3,9,20,null,null,15,7] 
输出: 24 
解释: 在这个>二叉中,有两个左叶子,分别是 9 和 15,所以返回 24示例 2:
输入: root = [1]
输出: 0
思路:

        判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。

(1)迭代法

/*** 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 sumOfLeftLeaves(TreeNode* root) {stack<TreeNode*> st;if (root == NULL) return 0;st.push(root);int result = 0;while (!st.empty()) {TreeNode* node = st.top();st.pop();if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) {result += node->left->val;}if (node->right) st.push(node->right);if (node->left) st.push(node->left);}return result;}
};

(2)递归法

/*** 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 sumOfLeftLeaves(TreeNode* root) {// 递归法if (root == nullptr) return 0;if (!root->left && !root->right) return 0;int leftNum = sumOfLeftLeaves(root->left);if (root->left && !root->left->left && !root->left->right) {leftNum += root->left->val;}int rightNum = sumOfLeftLeaves(root->right);return leftNum + rightNum;}
};

2. 找左下角的值

513. 找左下角的值 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/find-bottom-left-tree-value/submissions/567011451/

        给定一个>二叉的 根节点 root,请找出该>二叉的 最底层 最左边 节点的值。假设>二叉中至少有一个节点。

示例 1:
输入: root = [2,1,3]
输出: 1

示例 2:
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7

(1)广度优先算法

/*** 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 findBottomLeftValue(TreeNode* root) {// 层序遍历queue<TreeNode*> record;int result = 0;if (root != nullptr) {record.push(root);result = root->val;}while (!record.empty()) {int size = record.size();for (int i = 0; i < size; i++) {TreeNode* node = record.front(); record.pop();if (i == 0) result = node->val;if (node->left) record.push(node->left);if (node->right) record.push(node->right);}}return result;}
};

(2)递归法

/*** 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 result;int maxdepth = INT_MIN;void traversal(TreeNode* node, int depth) {if (node == nullptr) return;if (!node->left && !node->right && depth > maxdepth) {maxdepth = depth;result = node->val;return;}traversal(node->left, depth + 1);traversal(node->right, depth + 1);}int findBottomLeftValue(TreeNode* root) {traversal(root, 0);return result;}
};

3. 路径总和

112. 路径总和 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/path-sum/description/

        给你>二叉的根节点 root 和一个表示目标和的整数 targetSum 。判断该中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

        叶子节点 是指没有子节点的节点。

示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:
输入:root = [1,2,3], targetSum = 5
输出:false
解释:中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:
输入:root = [], targetSum = 0
输出:false
解释:由于是空的,所以不存在根节点到叶子节点的路径。
思路:

        递归:可以用递减,让计数器 count 初始为目标和,然后每次减去遍历路径节点上的数值。如果最后 count == 0,同时到了叶子节点的话,说明找到了目标和。如果遍历到了叶子节点,count 不为 0,就是没找到。(代码中包含着回溯)

        迭代:栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和。c++就用pair结构来存放这个栈里的元素。

        定义为:pair<TreeNode*, int> pair<节点指针,路径数值> 这个为栈里的一个元素。

(1)递归法

/*** 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 PathSum(TreeNode* node, int targetSum) {if (node == nullptr) return false;if (!node->left && !node->right && targetSum == node->val) return true;bool leftTree = PathSum(node->left, targetSum - node->val);bool rightTree = PathSum(node->right, targetSum - node->val);return leftTree || rightTree;}bool hasPathSum(TreeNode* root, int targetSum) {if (root == nullptr) return false;return PathSum(root, targetSum);}
};

(2)迭代法

/*** 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 hasPathSum(TreeNode* root, int targetSum) {// 遍历法stack<pair<TreeNode*, int>> record;if (root == nullptr) return false;record.push(pair<TreeNode*, int>(root, root->val));while (!record.empty()) {pair<TreeNode*, int> node = record.top();record.pop();if (!node.first->left && !node.first->right && node.second == targetSum) return true;if (node.first->right) {record.push(pair<TreeNode*, int>(node.first->right,node.second + node.first->right->val));}if (node.first->left) {record.push(pair<TreeNode*, int>(node.first->left,node.second + node.first->left->val));}}return false;}
};

4. 从中序与后序遍历序列构造>二叉

106. 从中序与后序遍历序列构造>二叉 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/

        给定两个整数数组 inorder 和 postorder ,其中 inorder 是>二叉的中序遍历, postorder 是同一棵的后序遍历,请你构造并返回这颗 >二叉 。

示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]示例 2:
输入:inorder = [-1], postorder = [-1]
输出:[-1]
思路:

递归:

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

/*** 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* bTree(vector<int>& inorder, int inorderbegin, int inorderend,vector<int>& postorder, int postorderbegin, int postorderend) {if (postorderbegin == postorderend) return nullptr;// 获取根元素int mid = postorder[postorderend - 1];TreeNode* root = new TreeNode(mid);if (postorderend - postorderbegin == 1) return root;// 找到中序遍历中的根元素int inorderIndex;for (inorderIndex = inorderbegin; inorderIndex < inorderend; inorderIndex++) {if (mid == inorder[inorderIndex]) break;}// 中序遍历更新索引 [)int inorderbeginleft = inorderbegin;int inorderendleft = inorderIndex;int inorderbeginright = inorderIndex + 1;int inorderendright = inorderend;// 后序遍历更新索引 [)int postorderbeginleft = postorderbegin;int postorderendleft = postorderbeginleft + (inorderIndex - inorderbegin);int postorderbeginright = postorderendleft;int postorderendright = postorderend - 1;// for (int i = inorderbeginleft; i < inorderendleft; i++) {//     cout << inorder[i] << " ";// }// cout << endl;// for (int i = inorderbeginright; i < inorderendright; i++) {//     cout << inorder[i] << " ";// }// cout << endl;// for (int i = postorderbeginleft; i < postorderendleft; i++) {//     cout << postorder[i] << " ";//     // cout << i << " ";// }// cout << endl;// for (int i = postorderbeginright; i < postorderendright; i++) {//     cout << postorder[i] << " ";//     // cout << i << " ";// }// cout << endl;root->left = bTree(inorder, inorderbeginleft, inorderendleft,postorder, postorderbeginleft, postorderendleft);root->right = bTree(inorder, inorderbeginright, inorderendright,postorder, postorderbeginright, postorderendright);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if (!inorder.size() || !postorder.size()) return nullptr;return bTree(inorder, 0, inorder.size(), postorder, 0, postorder.size());}
};

5. 从前序与中序遍历序列构造>二叉

105. 从前序与中序遍历序列构造>二叉 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/

        给定两个整数数组 preorder 和 inorder ,其中 preorder 是>二叉的先序遍历, inorder 是同一棵的中序遍历,请构造>二叉并返回其根节点。

示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
/*** 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* bTree(vector<int>& preorder, int preorderbegin, int preorderend,vector<int>& inorder, int inorderbegin, int inorderend) {if (preorderbegin == preorderend) return nullptr;// 获取顶点节点int mid = preorder[preorderbegin];TreeNode* root = new TreeNode(mid);// 中序中遍历找到节点索引 [inorderbegin, inorderend)int inorderIndex;for (inorderIndex = inorderbegin; inorderIndex < inorderend; inorderIndex++) {if (mid == inorder[inorderIndex]) break;}// 更新前序遍历的索引 [preorderbegin, preorderend)int preorderbeginleft = preorderbegin + 1; int preorderendleft = preorderbegin + (inorderIndex - inorderbegin) + 1;int preorderbeginright = preorderendleft;int preorderendright = preorderend;// 更新中序遍历的索引 [inorderbegin, inorderend)int inorderbeginleft = inorderbegin;int inorderendleft = inorderIndex;int inorderbeginright = inorderIndex + 1;int inorderendright = inorderend;// for (int i = preorderbeginleft; i < preorderendleft; i++) {//     cout << preorder[i] << " ";// }// cout << endl;// for (int i = preorderbeginright; i < preorderendright; i++) {//     cout << preorder[i] << " ";// }// cout << endl;// for (int i = inorderbeginleft; i < inorderendleft; i++) {//     cout << inorder[i] << " ";// }// cout << endl;// for (int i = inorderbeginright; i < inorderendright; i++) {//     cout << inorder[i] << " ";// }// cout << endl;root->left = bTree(preorder, preorderbeginleft, preorderendleft,inorder, inorderbeginleft, inorderendleft);root->right = bTree(preorder, preorderbeginright, preorderendright,inorder, inorderbeginright, inorderendright);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if (!preorder.size() || !inorder.size()) return nullptr;return bTree(preorder, 0, preorder.size(), inorder, 0, inorder.size());}
};

6. 最大>二叉

654. 最大>二叉 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/maximum-binary-tree/description/

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

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边 的 子数组前缀上 构建左子
  3. 递归地在最大值 右边 的 子数组后缀上 构建右子

返回 nums 构建的 最大>二叉 。

示例 1:
输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。- 空数组,无子节点。- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。- 空数组,无子节点。- 只有一个元素,所以子节点是一个值为 1 的节点。- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。- 只有一个元素,所以子节点是一个值为 0 的节点。- 空数组,无子节点。

示例 2:
输入:nums = [3,2,1]
输出:[3,null,2,null,1]
/*** 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* buildTree(vector<int>& nums, int beginIndex, int endIndex) {if (beginIndex == endIndex) return nullptr;// 获取中心元素int midIndex = beginIndex;for (int i = beginIndex; i < endIndex; i++) {midIndex = nums[i] > nums[midIndex] ? i : midIndex;}// cout << midIndex << endl;TreeNode* root = new TreeNode(nums[midIndex]);// 重定义左右节点int leftbeginIndex = beginIndex;int leftendIndex = midIndex;int rightbeginIndex = midIndex + 1;int rightendIndex = endIndex;// for (int i = leftbeginIndex; i < leftendIndex; i++) {//     cout << nums[i] << " ";// }// cout << endl;// for (int i = rightbeginIndex; i < rightendIndex; i++) {//     cout << nums[i] << " ";// }// cout << endl;root->left = buildTree(nums, leftbeginIndex, leftendIndex);root->right = buildTree(nums, rightbeginIndex, rightendIndex);return root;}TreeNode* constructMaximumBinaryTree(vector<int>& nums) {if (nums.size() == 0) return nullptr;return buildTree(nums, 0, nums.size());}
};

树>二叉">7. 合并>二叉

617. 合并>二叉 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/merge-two-binary-trees/description/

        给你两棵>二叉: root1 和 root2 。

        想象一下,当你将其中一棵覆盖到另一棵之上时,两棵上的一些节点将会重叠(而另一些不会)。你需要将这两棵合并成一棵新>二叉。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新>二叉的节点。

        返回合并后的>二叉

        注意: 合并过程必须从两个的根节点开始。

示例 1:
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]示例 2:
输入:root1 = [1], root2 = [1,2]
输出:[2,2]
思路:

        递归:因为是传入了两个,那么就有两个遍历的节点root1 和 root2,如果root1 == NULL 了,两个合并就应该是 root2 了(如果root2也为NULL也无所谓,合并之后就是NULL)。反过来如果root2 == NULL,那么两个数合并就是root1(如果root1也为NULL也无所谓,合并之后就是NULL)。

(1)递归法

/*** 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* mergeTrees(TreeNode* root1, TreeNode* root2) {// 递归if (root1 == nullptr) return root2;if (root2 == nullptr) return root1;TreeNode* root = new TreeNode(0);root->val = root1->val + root2->val;root->left = mergeTrees(root1->left, root2->left);root->right = mergeTrees(root1->right, root2->right);return root;}
};

(2)迭代法

/*** 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* mergeTrees(TreeNode* t1, TreeNode* t2) {if (t1 == NULL) return t2;if (t2 == NULL) return t1;queue<TreeNode*> que;   // 用于处理两棵节点都有数的时候que.push(t1);que.push(t2);while(!que.empty()) {TreeNode* node1 = que.front(); que.pop();TreeNode* node2 = que.front(); que.pop();// 此时两个节点一定不为空,val相加node1->val += node2->val;// 如果两棵左节点都不为空,加入队列if (node1->left != NULL && node2->left != NULL) {que.push(node1->left);que.push(node2->left);}// 如果两棵右节点都不为空,加入队列if (node1->right != NULL && node2->right != NULL) {que.push(node1->right);que.push(node2->right);}// 当t1的左节点 为空 t2左节点不为空,就赋值过去if (node1->left == NULL && node2->left != NULL) {node1->left = node2->left;}// 当t1的右节点 为空 t2右节点不为空,就赋值过去if (node1->right == NULL && node2->right != NULL) {node1->right = node2->right;}}return t1;}
};

8. 二叉搜索中的搜索

700. 二叉搜索中的搜索 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/search-in-a-binary-search-tree/description/

        给定二叉搜索(BST)的根节点 root 和一个整数值 val

        你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子。 如果节点不存在,则返回 null 。

示例 1:
输入:root = [4,2,7,1,3], val = 2
输出:[2,1,3]

示例 2:
输入:root = [4,2,7,1,3], val = 5
输出:[]

(1)递归法

/*** 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* searchBST(TreeNode* root, int val) {if (root == NULL || root->val == val) return root;TreeNode* result = NULL;if (root->val > val) result = searchBST(root->left, val);if (root->val < val) result = searchBST(root->right, val);return result;}
};

(2)迭代法

/*** 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* searchBST(TreeNode* root, int val) {while (root != nullptr) {if (root->val > val) root = root->left;else if (root->val < val) root = root->right;else return root;}return nullptr;}
};

9. 验证二叉搜索

98. 验证二叉搜索 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/validate-binary-search-tree/description/

        给你一个>二叉的根节点 root ,判断其是否是一个有效的二叉搜索

有效 二叉搜索定义如下:

  • 节点的左只包含 小于 当前节点的数。
  • 节点的右子只包含 大于 当前节点的数。
  • 所有左子和右子自身必须也是二叉搜索

示例 1:
输入:root = [2,1,3]
输出:true

示例 2:
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。
思路:

① 陷阱 1:

        不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。我们要比较的是 左子所有节点小于中间节点,右子所有节点大于中间节点。

② 陷阱 2:

        样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。此时可以初始化比较元素为 longlong 的最小值。

(1)递归法

/*** 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:vector<int> vec;    // 保存到数组中再进行比较void traversal(TreeNode* root) {if (root == NULL) return;traversal(root->left);vec.push_back(root->val); // 将二叉搜索转换为有序数组traversal(root->right);}public:bool isValidBST(TreeNode* root) {vec.clear(); // 不加这句在leetcode上也可以过,但最好加上traversal(root);for (int i = 1; i < vec.size(); i++) {// 小于等于,搜索里不能有相同元素if (vec[i] <= vec[i - 1]) return false;}return true;}
};// 方法二:记录递归的上个节点
class Solution {
public:TreeNode* pre = nullptr;    // 中序遍历,记录前一个节点,只要出现正在遍历的值小于上个节点的值,就返回 falsebool isValidBST(TreeNode* root) {if (root == nullptr) return true;bool leftTree = isValidBST(root->left);if (pre && root->val <= pre->val) return false;else pre = root;bool rightTree = isValidBST(root->right);return leftTree && rightTree;}
};

(2)迭代法

/*** 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) {stack<TreeNode*> record;if (root != nullptr) record.push(root);TreeNode* cur = nullptr;while (!record.empty()) {TreeNode* node = record.top();record.pop();if (node != nullptr) {if (node->right) record.push(node->right);record.push(node);record.push(nullptr);if (node->left) record.push(node->left);}else {node = record.top();record.pop();if (cur && node->val <= cur->val) return false;cur = node; }}return true;}
};

10. 二叉搜索的最小绝对差

530. 二叉搜索的最小绝对差 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/

        给你一个二叉搜索的根节点 root ,返回 中任意两不同节点值之间的最小差值 。差值是一个正数,其数值等于两值之差的绝对值。

示例 1:
输入:root = [4,2,6,1,3]
输出:1

示例 2:
输入:root = [1,0,48,null,null,12,49]
输出:1
/*** 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 getMinimumDifference(TreeNode* root) {stack<TreeNode*> record;if (root != nullptr) record.push(root);TreeNode* cur = nullptr;int result = INT_MAX;while (!record.empty()) {TreeNode* node = record.top();record.pop();if (node != nullptr) {if (node->right) record.push(node->right);record.push(node);record.push(nullptr);if (node->left) record.push(node->left);}else {node = record.top();record.pop();if (cur) result = min(result, (node->val - cur->val));cur = node;}}return result;}
};

11. 二叉搜索中的众数

501. 二叉搜索中的众数 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/find-mode-in-binary-search-tree/description/

        给你一个含重复值的二叉搜索(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

        如果中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

  • 结点左子中所含节点的值 小于等于 当前节点的值
  • 结点右子中所含节点的值 大于等于 当前节点的值
  • 左子和右子都是二叉搜索

示例 1:
输入:root = [1,null,2,2]
输出:[2]示例 2:
输入:root = [0]
输出:[0]
思路 1:

        这个都遍历了,用map统计频率。想直接对 map 中的 value 排序,还真做不到,C++中如果使用 std::map 或者 std::multimap 可以对 key 排序,但不能对value排序。所以要把map转化数组即 vector,再进行排序,当然vector里面放的也是pair<int, int>类型的数据,第一个int为元素,第二个int为出现频率。

        数组 vector 中已经是存放着按照频率排好序的pair,那么把前面高频的元素取出来就可以了。

思路 2:

        只需要遍历一次就可以找到所有的众数。频率count 大于 maxCount的时候,不仅要更新 maxCount(要把这个元素加入到结果集中),而且要清空结果集(以下代码为result数组),因为结果集之前的元素都失效了。

(1)递归法

/*** 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 searchBST(unordered_map<int, int>& map, TreeNode* root) {if (root == nullptr) return;map[root->val]++;searchBST(map, root->left);searchBST(map, root->right);return;}bool static cmp(const pair<int, int> x, const pair<int, int> y) {return x.second > y.second;}vector<int> findMode(TreeNode* root) {// C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序// 设置大根堆unordered_map<int, int> map;vector<int> result;if (root == nullptr) return result;searchBST(map, root);// 放到 vector 中进行排序vector<pair<int, int>> vec(map.begin(), map.end());sort(vec.begin(), vec.end(), cmp);result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {if (vec[i].second == vec[i - 1].second) result.push_back(vec[i].first);else break;}return result;}
};

(2)迭代法

/*** 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 static cmp(const pair<int, int> x, const pair<int, int> y) {return x.second > y.second;}vector<int> findMode(TreeNode* root) {// 设置大根堆unordered_map<int, int> map;stack<TreeNode*> record;vector<int> result;if (root == nullptr) return result;record.push(root);while (!record.empty()) {TreeNode* node = record.top();record.pop();if (node != nullptr) {if (node->right) record.push(node->right);if (node->left) record.push(node->left);record.push(node);record.push(nullptr);}else {node = record.top();record.pop();map[node->val]++;}}// 放到 vector 中进行排序vector<pair<int, int>> vec(map.begin(), map.end());sort(vec.begin(), vec.end(), cmp);result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {if (vec[i].second == vec[i - 1].second) result.push_back(vec[i].first);else break;}return result;}
};// 方法二:(一次遍历)
class Solution {
public:vector<int> findMode(TreeNode* root) {stack<TreeNode*> st;TreeNode* cur = root;TreeNode* pre = NULL;int maxCount = 0; // 最大频率int count = 0; // 统计频率vector<int> result;while (cur != NULL || !st.empty()) {if (cur != NULL) { // 指针来访问节点,访问到最底层st.push(cur); // 将访问的节点放进栈cur = cur->left;                // 左} else {cur = st.top();st.pop();                       // 中if (pre == NULL) { // 第一个节点count = 1;} else if (pre->val == cur->val) { // 与前一个节点数值相同count++;} else { // 与前一个节点数值不同count = 1;}if (count == maxCount) { // 如果和最大值相同,放进result中result.push_back(cur->val);}if (count > maxCount) { // 如果计数大于最大值频率maxCount = count;   // 更新最大频率result.clear();     // 很关键的一步,不要忘记清空result,之前result里的元素都失效了result.push_back(cur->val);}pre = cur;cur = cur->right;               // 右}}return result;}
};


http://www.ppmy.cn/ops/118230.html

相关文章

Serverless and Go

本篇内容是根据2019年8月份Serverless and Go音频录制内容的整理与翻译, Johnny、Mat、Jaana 和特邀嘉宾 Stevenson Jean-Pierre 讨论了 Go 世界中的Serverless。什么是Serverless&#xff0c;Serverless适用于哪些用例&#xff0c;有哪些权衡&#xff0c;以及如何在Serverles…

project_object_model_3d

**( : ModelContours : ObjectModel3D, CamParam, Pose, GenParamName, GenParamValue : )** ModelContours&#xff1a;投影成的轮廓线 ObjectModel3D&#xff1a;被投影的3D模型&#xff0c;做过三维造型的话&#xff0c;我觉得这里就是求视图&#xff0c;所谓左视图&#…

828华为云征文|部署基于 LLM 的私有知识库系统 AnythingLLM

部署基于 LLM 的私有知识库系统 AnythingLLM 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 AnythingLLM3.1 AnythingLLM 介绍3.2 AnythingLLM 部署3.3 AnythingLLM 使用 …

Arch - 架构安全性_保密(Confidentiality)

文章目录 OverView导图保密保密强度与成本客户端加密密码存储与验证 Code总结 OverView 即使只限定在“软件架构设计”这个语境下&#xff0c;系统安全仍然是一个很大的话题。 接下来我们将对系统安全架构的各个方面进行详细分析&#xff0c;包括认证、授权、凭证、保密、传输…

解决 Pandas 中的 XLRDError:处理 “Excel xlsx file; not supported” 错误

解决 Pandas 中的 XLRDError&#xff1a;处理 “Excel xlsx file; not supported” 错误 在处理数据分析任务时&#xff0c;使用 Python 的 Pandas 库来读取 Excel 文件是一种常见的做法。然而&#xff0c;从 Pandas 1.2.0 版本开始&#xff0c;默认使用的 xlrd 库不再支持 .x…

Linux驱动开发初识

Linux驱动开发初识 文章目录 Linux驱动开发初识一、驱动的概念1.1 什么是驱动&#xff1a;1.2 驱动的分类&#xff1a; 二、设备的概念2.1 主设备号&次设备号&#xff1a;2.2 设备号的作用&#xff1a; 三、设备驱动整体调用过程3.1 上层用户操控设备的流程&#xff1a;3.2…

深度学习(5):逻辑斯蒂回归Logistic

文章目录 一、逻辑斯蒂回归&#xff08;Logistic Regression&#xff09;二、KL 散度&#xff08;相对熵&#xff09;三、交叉熵&#xff08;Cross-Entropy&#xff09;四、关系五、总结 一、逻辑斯蒂回归&#xff08;Logistic Regression&#xff09; 概述 逻辑斯蒂回归是一种…

Elasticsearch在大数据处理中的优势

Elasticsearch 在大数据处理中的优势主要体现在以下几个方面&#xff1a; 1. 分布式架构 水平扩展&#xff1a;Elasticsearch 设计为分布式系统&#xff0c;可以轻松地通过增加节点来水平扩展&#xff0c;处理 PB 级别的数据。数据分片和复制&#xff1a;数据自动分片并跨多个…