题目链接:669. 修剪二叉搜索树
1.思路
题目:
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
2.我们前序遍历找到不符合的点,然后再遍历左右边可能符合条件的点,直到遍历到最后,条件中返回的是不包含不符合范围的左子树或右子树。
2.递归法
class Solution {
public:
TreeNode* traversal(TreeNode* root, int low, int high) {
if (root == NULL) return NULL;
if (root->val < low) {
TreeNode*right = traversal(root->right, low, high);
return right;
}
if (root->val > high) {
TreeNode* left = traversal(root->left, low, high);
return left;
}
root->left = traversal(root->left, low, high);
root->right = traversal(root->right, low, high);
return root;
}
TreeNode* trimBST(TreeNode* root, int low, int high) {
return traversal(root, low, high);
}
};
精简后:
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr) return nullptr;
if (root->val < low) return trimBST(root->right, low, high);
if (root->val > high) return trimBST(root->left, low, high);
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};
3.递归三部曲
1.确定返回类型和参数类型:因为是修剪二叉树,最后还是返回二叉树,为treenode,传入返回和根节点
2.确定终止条件:当遍历到空节点时,返回空给叶子结点的左右子树
3.确定单层递归的逻辑:遍历二叉树中的结点需要先判断结点符不符合规格,所以先序判断一下,不符合规格就返回符合规格的子树,子树还要进行判断最后返回符合规格的叶子结点,最后返回root,再到上一层,因为在中的逻辑中已经跳过了不符合逻辑的点返回上一层,所以最后就是修剪后的子树
推测靠先序,理解看后序
题目链接:108. 将有序数组转换为二叉搜索树
1.思路
将数组构造成平衡二叉搜索树,一般用前序遍历,挑选出中间点,再递归挑选左右边子树的根。奇数和偶数相同的逻辑。
2.递归法
class Solution {
public:
TreeNode*traversal(vector<int>& nums, int left, int right) {
if (left > right) return NULL;
int mid = left + right >> 1;
TreeNode* root = new TreeNode(nums[mid]);
root->left = traversal(nums,left, mid - 1);
root->right = traversal(nums, mid + 1, right);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
return traversal(nums, 0, nums.size() - 1);
}
};
3.递归三部曲
1.确定返回类型和参数类型:因为要构造二叉树,所以就要返回根结点TreeNode ,传入数组,因为每一次我们都要缩减数组范围,所以需要传入左边界和右边界。
左边界和右边界的定义:都可以。但后面的逻辑会不相同
2.确定终止条件:当遇到空结点时返回空为叶子结点的左右子树。
3.确定单层递归的逻辑,因为构造二叉树,每次都前序新增结点,左右遍历再把结点加入左子树和右子树,最后从叶子结点逐步返回到了根结点。
题目链接:538. 把二叉搜索树转换为累加树
1.思路
题目的意思是把比当前结点大的(就是右子树)值和当前结点的值相加变成当前结点的值。因为是二叉搜索树,要充分利用二叉搜索树的特性,为中序遍历,又因为是把大的相加,需要倒序,所以用右中左。利用双指针不断把值传给上一层。
2.递归法
class Solution {
public:
TreeNode*pre = nullptr;
void traversal(TreeNode* cur) {
if (cur == nullptr) return;
traversal(cur->right);
if (pre != nullptr) {
cur->val += pre->val;
}
pre = cur;
traversal(cur->left);
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
3.递归三部曲
1.确定返回类型和返回参数:因为是修改结点,直接返回void,传入树的根结点。
2.确定返回类型,当遍历到空结点时,直接返回上一层,同步指针。
3.确定单层递归的逻辑:因为是中序遍历,结点的值都是有顺序的遍历到的,每次遍历都需要同步结点,同步前需要进行相加如果这个不是叶子结点的时候。最后不断向上。