0
点赞
收藏
分享

微信扫一扫

LeetCode二叉树练习(二)


一、前言

二叉搜索树是面试中比较常见的一种树形结构,往往利用二叉树的特性可以使得题目的复杂度得到很大程度的降低。以下罗列一些经典的题目。

二、经典题目

1 二叉搜索树中的搜索

利用二叉树的性质,非空情况下,左子树的节点小于根节点,右子树的节点大于根节点。

class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if (root == NULL || root->val == val) return root;
if (root->val > val) return searchBST(root->left, val);
if (root->val < val) return searchBST(root->right, val);
return NULL;
}
};

2 验证二叉搜索树

98.验证二叉搜素树

中序遍历下的二叉搜索树的序列是递增的。

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;
}
};

思考时注意,二叉搜索树的节点值:


我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。



样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。

此时可以初始化比较元素为longlong的最小值。


class Solution {
public:
TreeNode* pre = NULL; // 用来记录前一个节点
bool isValidBST(TreeNode* root) {
if (root == NULL) return true;
bool left = isValidBST(root->left);

if (pre != NULL && pre->val >= root->val) return false;// 注意是 >=
pre = root; // 记录前一个节点

bool right = isValidBST(root->right);
return left && right;
}
};

3 二叉搜素树中寻找

​​530. 二叉搜索树的最小绝对差​​

题目:


给你一个二叉搜索树的根节点 ​​root​​ ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

LeetCode二叉树练习(二)_算法

输入:root = [4,2,6,1,3]
输出: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* pre = nullptr;
int res = INT_MAX;
int getMinimumDifference(TreeNode* root) {
if(root == nullptr) return 0;
getMinimumDifference(root->left);
if(pre!=nullptr) res = min(res, abs(root->val - pre->val));
pre = root;
getMinimumDifference(root->right);
return res;
}
};

4 二叉搜索树中的众数

501.二叉搜索树中的众数

class Solution {
private:
int maxCount; // 最大频率
int count; // 统计频率
TreeNode* pre;
vector<int> result;
void searchBST(TreeNode* cur) {
if (cur == NULL) return ;

searchBST(cur->left); // 左
// 中
if (pre == NULL) { // 第一个节点
count = 1;
} else if (pre->val == cur->val) { // 与前一个节点数值相同
count++;
} else { // 与前一个节点数值不同
count = 1;
}
pre = cur; // 更新上一个节点

if (count == maxCount) { // 如果和最大值相同,放进result中
result.push_back(cur->val);
}

if (count > maxCount) { // 如果计数大于最大值频率
maxCount = count; // 更新最大频率
result.clear(); // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
result.push_back(cur->val);
}

searchBST(cur->right); // 右
return ;
}

public:
vector<int> findMode(TreeNode* root) {
count = 0;
maxCount = 0;
TreeNode* pre = NULL; // 记录前一个节点
result.clear();

searchBST(root);
return result;
}
};

5 二叉树的最近公共祖先

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


给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

LeetCode二叉树练习(二)_二叉搜索树_02

示例 1: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

示例 2: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。


思路

自低向上->回溯->后序遍历

最近公共祖先出现的位置:

该节点的左或者右为p或者q

节点本身q(q),它拥有一个子孙节点q§

如果递归函数有返回值,如何区分要搜索的是一条边还是搜索整个树呢?

搜索一条边的写法:

if (递归函数(root->left)) return ;

if (递归函数(root->right)) return ;

搜索整个树写法:

left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;

看出区别了没?

在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)

在本题中:

LeetCode二叉树练习(二)_最近公共祖先_03

LeetCode二叉树练习(二)_二叉搜索树_04

class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 后序遍历
if(root == p || root == q || root == nullptr) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if(left!= nullptr && right != nullptr) return root;
else if(left!= nullptr && right == nullptr) return left;
else if(right!= nullptr && left == nullptr) return right;
else{
return nullptr;
}
return root;
}
};

牛客网上的:

return left==nullptr ? right : (right==nullptr ? left : root);

6 二叉搜索树的最近公共祖先

  1. 二叉搜索树的最近公共祖先


给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]


class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 借助二叉树的特性 定位
if(root == nullptr) return root;

if(root->val > p->val && root->val > q->val){
TreeNode* left = lowestCommonAncestor(root->left, p, q);
if(left!=nullptr) return left;
}
if(root->val < p->val && root->val < q->val){
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if(right!= nullptr) return right;
}
return root;
}
};
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root->val > p->val && root->val > q->val) {
return lowestCommonAncestor(root->left, p, q);
} else if (root->val < p->val && root->val < q->val) {
return lowestCommonAncestor(root->right, p, q);
} else return root;
}
};

7 二叉搜索树中的插入操作

701.二叉搜索树中的插入操作


给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。


答案不唯一。

class Solution {
private:
TreeNode* parent;
void traversal(TreeNode* cur, int val) {
if (cur == NULL) {
TreeNode* node = new TreeNode(val);
if (val > parent->val) parent->right = node;
else parent->left = node;
return;
}
parent = cur;
if (cur->val > val) traversal(cur->left, val);
if (cur->val < val) traversal(cur->right, val);
return;
}

public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
parent = new TreeNode(0);
if (root == NULL) {
root = new TreeNode(val);
}
traversal(root, val);
return root;
}
};


举报

相关推荐

0 条评论