669. 修剪二叉搜索树
1.递归法(本题递归法相对容易理解一些,根节点在范围内,则依次递归左右子树并用左右指针接住递归结果。根节点在范围左边,则左子树肯定也全部在范围左边,直接淘汰左子树,递归右子树。根节点在范围右边,则右子树也全部在范围右边,直接淘汰右子树,递归左子树。)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
struct TreeNode* trimBST(struct TreeNode* root, int low, int high) {//递归法
if(root==NULL) return NULL;//终止条件
//根节点比low小,左子树肯定不符合,淘汰左子树,返回修剪好的右子树
if(root->val<low) return trimBST(root->right,low,high);
//根节点比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;
}
2.迭代法(迭代的思想是先找到第一个在范围内的根节点,然后依次处理这个结点的左右子树。根节点在范围内,则其左子树范围全部在high左边。也就是说如果左子树的根节点如果在范围内,则左子树的右子树一定在范围内,左子树的左子树可能在范围内。如果左子树的根节点不在范围内,则左子树的左子树一定不在范围内,左子树的右子树可能在范围内。根据这个逻辑依次往下判断,直至叶子结点,根节点的右子树同理。)
/**
* 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* trimBST(TreeNode* root, int low, int high) {
if (root == NULL)
return NULL;
while (root != NULL && (root->val < low || root->val > high)) {
if (root->val < low)
root = root->right;
else
root = root->left; //找到第一个root值在给定范围的结点
}
TreeNode* cur = root;
while (cur !=
NULL) { //此时结点左子树都比high小,只需要修剪掉比low小的结点
while (cur->left && cur->left->val < low) {
cur->left = cur->left->right; //在左子树中找到符合范围的结点
}
cur = cur->left; //循环判断找到的子树
}
cur = root;
while (cur != NULL) {
while (cur->right && cur->right->val > high) {
cur->right = cur->right->left;
}
cur = cur->right;
}
return root;
}
};
108.将有序数组转换为二叉搜索树
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* sortedArrayToBST(vector<int>& nums) {
int size=nums.size()-1;
if(size==-1) return nullptr;//递归终止条件
TreeNode* root=new TreeNode(nums[size/2]);//取中间元素
vector<int> leftnums(nums.begin(),nums.begin()+size/2);//划分左右数组
root->left=sortedArrayToBST(leftnums);//递归左右数组
vector<int> rightnums(nums.begin()+size/2+1,nums.end());
root->right=sortedArrayToBST(rightnums);
return root;
}
};
/**
* 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* traversal(vector<int>& nums,int left,int right){
if(left>right) return nullptr;
int mid=(left+right)/2;
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) {
TreeNode* root=traversal(nums,0,nums.size()-1);
return root;
}
};
2.迭代法(迭代法的实现是借助3个辅助队列,一个放结点另两个放左右区间的下标,根据左右区间下标找到数组中间值赋值给结点,然后更新辅助队列,依次重复这个过程)
/**
* 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* sortedArrayToBST(vector<int>& nums) {
if (nums.size() == 0) return nullptr;
TreeNode* root = new TreeNode(0); // 初始根节点
queue<TreeNode*> nodeQue; // 放遍历的节点
queue<int> leftQue; // 保存左区间下标
queue<int> rightQue; // 保存右区间下标
nodeQue.push(root); // 根节点入队列
leftQue.push(0); // 0为左区间下标初始位置
rightQue.push(nums.size() - 1); // nums.size() - 1为右区间下标初始位置
while (!nodeQue.empty()) {
TreeNode* curNode = nodeQue.front();
nodeQue.pop();
int left = leftQue.front(); leftQue.pop();
int right = rightQue.front(); rightQue.pop();
int mid = left + ((right - left) / 2);
curNode->val = nums[mid]; // 将mid对应的元素给中间节点
if (left <= mid - 1) { // 处理左区间
curNode->left = new TreeNode(0);
nodeQue.push(curNode->left);
leftQue.push(left);
rightQue.push(mid - 1);
}
if (right >= mid + 1) { // 处理右区间
curNode->right = new TreeNode(0);
nodeQue.push(curNode->right);
leftQue.push(mid + 1);
rightQue.push(right);
}
}
return root;
}
};
538.把二叉搜索树转换为累加树
这道题一上来看起来有点复杂,但其实读懂题目后会发现其实是道easy题。二叉搜索树如果中序遍历序列以数组形式输出会发现它是一个非递减序列,题目要求累加树每个结点的值等于二叉搜索树上所有结点值>=这个结点值之和。放到它的中序遍历数组上就是,新数组每个新元素的值都等于之前数组这个元素包括它本身与后面所有元素之和。第一个元素就等于从第一个元素一直加到最后一个元素的和,第二个元素就等于从第二个一直加到最后一个元素的和,依此类推。我们发现这样每次都会有大量重复的计算,那有没有什么改进措施呢?我们发现最后一个元素只有它本身>=自己(因为题目说了每个结点值不同),倒数第二个元素只有它本身和最后一个元素值>=它本身。于是我们就有了想法,从后往前遍历,也就是右中左,累加每个结点的元素值,再把累加值赋给当前遍历结点。
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* convertBST(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur=root;
int sum=0;
while(cur!=NULL||!st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->right;
}
else{
cur=st.top();
st.pop();
sum+=cur->val;
cur->val=sum;
cur=cur->left;
}
}
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://递归法
int sum=0;
void traversal(TreeNode* root){
if(root==nullptr) return;
traversal(root->right);
sum+=root->val;//累加
root->val=sum;
traversal(root->left);
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
今日总结:大海啊,你全部都是水!