669. 修剪二叉搜索树
思路
- 截止条件:为空节点
- 单层递归:值如果小于
low
,值如果大于high
,如果值在low
和high
之间,则递归左右节点 - 返回:返回根节点
代码
- 递归
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (!root) return nullptr;
if (root->val < low)
return trimBST(root->right, low, high);
if (root->val > high)
return trimBST(root->left, low, high);
if (root->val >= low && root->val <= high){
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
}
return root;
}
};
- 迭代
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (!root) return nullptr;
while (root != nullptr && (root->val < low || root->val > high)) {
if (root->val < low) root = root->right;
else root = root->left;
} // 找到在范围中的根节点
auto cur = root;
while (cur){
while (cur->left && cur->left->val < low){
cur->left = cur->left->right;
}
cur = cur->left;
} // 找寻符合要求的左子树
cur = root;
while (cur){
while (cur->right && cur->right->val > high){
cur->right = cur->right->left;
}
cur = cur->right;
}//找寻符合要求的右子树
return root;
}
};
108. 将有序数组转换为二叉搜索树
思路
- 有序数组,中间对半分,左侧一直向左,右侧一直向右
- 有序数组,中间对半分,每次都递归左侧这部分作为左子树再构建,右侧作为右子树再构建一个,注意截止条件
代码
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return dfs(nums, 0, nums.size() - 1);
}
TreeNode* dfs(vector<int>& nums, int left, int right){
if (left > right) return nullptr;
int mid = (left + right) >> 1;
TreeNode* root = new TreeNode(nums[mid]);
root->left = dfs(nums, left, mid - 1);
root->right = dfs(nums, mid + 1, right);
return root;
}
};
538. 把二叉搜索树转换为累加树
思路
- 第一次中序遍历记录
sum
总和,第二次中序遍历更改val
值 - 右中左
代码
class Solution {
public:
vector<int> a;
int sum = 0;
int cur = 0;
TreeNode* convertBST(TreeNode* root) {
dfs(root);
return dfs1(root);
}
void dfs(TreeNode* root){
if (!root) return;
dfs(root->left);
a.push_back(root->val);
sum += root->val;
dfs(root->right);
return;
}
TreeNode* dfs1(TreeNode* root){
if (!root) return nullptr;
dfs1(root->left);
cur = root->val;
root->val = sum;
sum -= cur;
dfs1(root->right);
return root;
}
};
- 迭代
class Solution {
public:
int pre = 0;
TreeNode* convertBST(TreeNode* root) {
if (!root) return nullptr;
stack<TreeNode*> stk;
auto cur = root;
while (!stk.empty() || cur != nullptr){
if (cur){
stk.push(cur);
cur = cur->right;
}else{
cur = stk.top();
stk.pop();
cur->val += pre;
pre = cur->val;
cur = cur->left;
}
}
return root;
}
};
总结
遍历方式
前中后序 层序,迭代+递归
性质
- 二叉树:是否对称
递归:后序,比较的是根节点的左子树与右子树是不是相互翻转
迭代:使用队列/栈将两个节点顺序放入容器中进行比较 - 二叉树:求最大深度
递归:后序,求根节点最大高度就是最大深度,通过递归函数的返回值做计算树的高度
迭代:层序遍历 - 二叉树:求最小深度
递归:后序,求根节点最小高度就是最小深度,注意最小深度的定义
迭代:层序遍历 - 二叉树:求有多少个节点
递归:后序,通过递归函数的返回值计算节点数量
迭代:层序遍历 - 二叉树:是否平衡
递归:后序,注意后序求高度和前序求深度,递归过程判断高度差
迭代:效率很低,不推荐 - 二叉树:找所有路径
递归:前序,方便让父节点指向子节点,涉及回溯处理根节点到叶子的所有路径
迭代:一个栈模拟递归,一个栈来存放对应的遍历路径 - 二叉树:递归中如何隐藏着回溯
- 二叉树:求左叶子之和
递归:后序,必须三层约束条件,才能判断是否是左叶子。
迭代:直接模拟后序遍历 - 二叉树:求左下角的值(opens new window)
递归:顺序无所谓,优先左孩子搜索,同时找深度最大的叶子节点。
迭代:层序遍历找最后一行最左边 - 二叉树:求路径总和
递归:顺序无所谓,递归函数返回值为bool类型是为了搜索一条边,没有返回值是搜索整棵树。
迭代:栈里元素不仅要记录节点指针,还要记录从头结点到该节点的路径数值总和
………………