时隔很多很多天又回来打卡了,坚持真的是一件很难的事情。
概念:左子树的值全部都小于根节点的值,右子树的值全部都大于根结点的值,左子树和右子树也是同样的原理。遍历的方式一般为中序遍历 即 : 左 -->根 -->右 。遍历完成后就是一个单调递增的函数。
1、递增顺序搜索树
给你一棵二叉搜索树,请 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。
示例 1:

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

输入:root = [5,1,7] 输出:[1,null,5,null,7]
提示:
- 树中节点数的取值范围是
[1, 100]
0 <= Node.val <= 1000
/**
* 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 {
vector<int> ret ;
void inoder(TreeNode *root){
if(root){
inoder(root->left);
ret.push_back(root->val);
inoder(root->right);
}
}
public:
TreeNode* increasingBST(TreeNode* root) {
ret.clear();
inoder(root);
TreeNode *head = new TreeNode(-1);
TreeNode *cret = head;
for(int i=0;i<ret.size();i++){
TreeNode *t = new TreeNode(ret[i]);
cret->right = t;
cret = t;
}
return head->right;
}
};
//下面是迭代的方法
/*
class Solution {
TreeNode *curt;
void inorder(TreeNode *root){
if(root){
inorder(root->left);
curt->right = root;
root->left = NULL;
curt = root;
inorder(root->right);
}
}
public:
TreeNode* increasingBST(TreeNode* root) {
TreeNode *head = new TreeNode(-1);
curt = head;
inorder(root);
return head->right;
}
};
*/
2、二叉搜索树中的搜索
给定二叉搜索树(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, 5000]
范围内 1 <= Node.val <= 107
root
是二叉搜索树1 <= val <= 107
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* searchBST(struct TreeNode* root, int val) {
if(root == NULL){
return NULL;
}
if(root->val > val){
return searchBST(root->left,val);
}else if(root->val < val){
return searchBST(root->right,val);
}
return root;
}
3、二叉搜索数范围和(左右子树与根和)
给定二叉搜索树的根结点 root
,返回值位于范围 [low, high]
之间的所有结点的值的和。
示例 1:
输入:root = [10,5,15,3,7,null,18], low = 7, high = 15 输出:32
示例 2:
输入:root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10 输出:23
提示:
- 树中节点数目在范围
[1, 2 * 104]
内 1 <= Node.val <= 105
1 <= low <= high <= 105
- 所有
Node.val
互不相同
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int rangeSumBST(struct TreeNode* root, int low, int high) {
if(root == NULL){
return 0;
}
int sum = 0;
if(low <= root->val && root->val <= high){
sum += root->val;
}
sum += rangeSumBST(root->left,low,high);
sum += rangeSumBST(root->right,low,high);
return sum;
}
4、二叉搜索树的最小绝对差
给你一个二叉搜索树的根节点 root
,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [4,2,6,1,3] 输出:1
示例 2:
输入:root = [1,0,48,null,null,12,49] 输出:1
提示:
- 树中节点的数目范围是
[2, 104]
0 <= Node.val <= 105
/**
* 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 {
int pre;
int ret;
void inorder(TreeNode *root){
if(root){
inorder(root->left);
ret = min(ret,(root->val - pre));
pre = root->val;
inorder(root->right);
}
}
public:
int getMinimumDifference(TreeNode* root) {
pre = -100000000;
ret = 100000000;
inorder(root);
return ret;
}
};
5、 两数之和 IV - 输入二叉搜索树(双指针,迭代)
给定一个二叉搜索树的 根节点 root
和一个整数 k
, 请判断该二叉搜索树中是否存在两个节点它们的值之和等于 k
。假设二叉搜索树中节点的值均唯一。
示例 1:
输入: root = [8,6,10,5,7,9,11], k = 12 输出: true 解释: 节点 5 和节点 7 之和等于 12
示例 2:
输入: root = [8,6,10,5,7,9,11], k = 22 输出: false 解释: 不存在两个节点值之和为 22 的节点
提示:
- 二叉树的节点个数的范围是
[1, 104]
. -104 <= Node.val <= 104
root
为二叉搜索树-105 <= k <= 105
/**
* 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) {}
* };
*/
/*常规做法或者叫迭代 O(n2)*/
class Solution {
vector <int> ret;
void inorder(TreeNode *root){
if(root){
inorder(root->left);
ret.push_back(root->val);
inorder(root->right);
}
}
public:
bool findTarget(TreeNode* root, int k) {
inorder(root);
for(int i=0; i<ret.size();++i){
for(int j=i+1; j<ret.size(); ++j){
if(ret[j] + ret[i] == k) return true;
}
}
return false;
}
};
/*双指针方式 O(n)*/
class Solution {
vector <int> ret;
void inorder(TreeNode *root){
if(root){
inorder(root->left);
ret.push_back(root->val);
inorder(root->right);
}
}
public:
bool findTarget(TreeNode* root, int k) {
ret.clear();
inorder(root);
int l=0, r = ret.size() - 1;
while(l < r){
if(ret[l] + ret[r] > k) {
r--;
}else if(ret[l] + ret[r] < k){
l++;
}else{
return true;
}
}
return false;
}
};
6、二叉搜索树中的众数
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2] 输出:[2]
示例 2:
输入:root = [0] 输出:[0]
提示:
- 树中节点的数目在范围
[1, 104]
内 -105 <= Node.val <= 105
/**
* 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 {
int pre, cnt;
int maxcnt;
vector<int> ret;
void vect(TreeNode *root){
if(root->val == pre){
cnt++;
}else {
pre = root->val;
cnt = 1;
}
if(cnt > maxcnt){
ret.clear();
maxcnt = cnt;
ret.push_back(root->val);
}else if(cnt == maxcnt){
ret.push_back(root->val);
}
}
void inorder(TreeNode *root){
if(root){
inorder(root->left);
vect(root);
inorder(root->right);
}
}
public:
vector<int> findMode(TreeNode* root) {
ret.clear();
pre=-100000000;
maxcnt = cnt = 0;
inorder(root);
return ret;
}
};
7、恢复二叉搜索树(核心:寻找逆序对)
给你二叉搜索树的根节点 root
,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。
示例 1:
输入:root = [1,3,null,null,2] 输出:[3,1,null,null,2] 解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
示例 2:
输入:root = [3,1,4,null,null,2] 输出:[2,1,4,null,null,3] 解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
提示:
- 树上节点的数目在范围
[2, 1000]
内 -231 <= Node.val <= 231 - 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 {
vector<TreeNode*> ret;
void inorder(TreeNode *root){
if(root){
inorder(root->left);
ret.push_back(root);
inorder(root->right);
}
}
public:
// 1 2 (7 4) 5 (6 3) 8 9
void recoverTree(TreeNode* root) {
ret.clear();
inorder(root);
TreeNode *x = NULL;
TreeNode *y = NULL;
for(int i=0; i<ret.size()-1; ++i){
if(ret[i]->val > ret[i+1]->val){
y = ret[i+1];
if(x == NULL){
x = ret[i];
}
}
}
if( x && y ){
int tmp = x->val;
x->val = y->val;
y->val = tmp;
}
}
};
8、删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
示例 1:
输入:root = [5,3,6,2,4,null,7], key = 3 输出:[5,4,6,2,null,null,7] 解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。 一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。 另一个正确答案是 [5,2,6,null,4,null,7]。
示例 2:
输入: root = [5,3,6,2,4,null,7], key = 0 输出: [5,3,6,2,4,null,7] 解释: 二叉树不包含值为 0 的节点
示例 3:
输入: root = [], key = 0 输出: []
提示:
- 节点数的范围
[0, 104]
. -105 <= Node.val <= 105
- 节点值唯一
root
是合法的二叉搜索树-105 <= key <= 105
/**
* 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 {
int finMin(TreeNode *root){
if(root->left){
return finMin(root->left);//递归寻找最小根节点
}
return root->val;
}
TreeNode *delRoot(TreeNode *root){
if(root->left == NULL){
TreeNode *delNode = root;
TreeNode *retNode = root->right;//右子树继承根节点
delete delNode;
return retNode;
}else if(root->right == NULL){
TreeNode *delNode = root;
TreeNode *retNode = root->left;//左子树继承根节点
delete delNode;
return retNode;
}else{
TreeNode *retNode = new TreeNode(0);
retNode->val = finMin(root->right); //找到右子树中最小值
retNode->right = deleteNode(root->right,retNode->val);
retNode->left = root->left;
return retNode;
}
return NULL;//左右子树都为空时直接返回空即为删除了节点
}
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(root == NULL){
return NULL;
}
if(root->val > key){//key小于根节点向左找
root->left = deleteNode(root->left,key);
}else if(root->val < key){//key大于根节点向右找
root->right = deleteNode(root->right,key);
}else {
return delRoot(root);//key等于
}
return root;
}
};