二叉树的定义
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x):val(x),left(NULL),right(NULL){}
};
二叉树的遍历方式
二叉树的递归遍历
前序遍历
class Solution{
public:
void traversal(TreeNode* cur,vector<int>& vec){
if(cur==NULL) return;
vec.push_back(cur->val);
traversal(cur->left,vec);
traversal(cur->right,vec);
}
vector<int> preorderTraversal(TreeNode* root){
vector<int> result;
traversal(root,result);
return result;
}
};
中序遍历
class Solution{
public:
void traversal(TreeNode* cur,vector<int>& vec){
if(cur==NULL) return;
traversal(cur->left,vec);
vec.push_back(cur->val);
traversal(cur->right,vec);
}
}
后序遍历
class Solution{
public:
void traversal(TreeNode* cur,vector<int>& vec){
if(cur==NULL) return;
traversal(cur->left,vec);
traversal(cur->right,vec);
vec.push_back(cur->val);
}
}
二叉树的迭代遍历
前序遍历
class Solution{
public:
vector<int> preorderTraversal(TreeNode* root){
stack<TreeNode*> st;
vector<int> result;
if (root == NULL) return result;
st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
st.pop();
result.push_back(node->val);
if(node->right) st.push(node->right);
if(node->left) st.push(node->left);
}
return result;
}
}
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop();
if (node->right) st.push(node->right); // 右
if (node->left) st.push(node->left); // 左
st.push(node); // 中
st.push(NULL);
} else {
st.pop();
node = st.top();
st.pop();
result.push_back(node->val);
}
}
return result;
}
};
中序遍历
class Solution{
public:
vector<int> inorderTraversal(TreeNode* root){
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur=root;
while(cur!=NULL||!st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->left;
}else{
cur=st.top():
st.pop();
result.push_back(cur->val);
cur=cur->right;
}
}
return result;
}
}
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
if (node->right) st.push(node->right); // 添加右节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node->left) st.push(node->left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.top(); // 重新取出栈中元素
st.pop();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
};
后序遍历
class Solution{
public:
vector<int> postorderTraversal(TreeNode* root){
vector<int> result;
stack<TreeNode*> st;
if(root==NULL) return result;
st.push(root);
while(!st.empty()){
TreeNode* cur=st.top();
st.pop();
result.push_back(cur->val);
if(cur->left) st.push_back(cur->left);
if(cur->right) st.push_back(cur->right);
}
reverse(result.begin(),result.end());
return result;
}
}
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop();
st.push(node); // 中
st.push(NULL);
if (node->right) st.push(node->right); // 右
if (node->left) st.push(node->left); // 左
} else {
st.pop();
node = st.top();
st.pop();
result.push_back(node->val);
}
}
return result;
}
};
二叉树的层序遍历
class Solution{
public:
vector<vector<int>> levelOrder(TreeNode* root){
queue<TreeNode*> que;
if(root!==NULL) que.push(root);
vector<vector<int>> result;
while(!que.empty()){
int size=que.size();
vector<int> vec;
for(int i=0;i<size;i++){
TreeNode* cur=que.top();
que.pop();
vec.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
result.push_back(vec);
}
return reuslt;
}
}
class Solution{
public:
void order(TreeNode* cur,vector<vector<int>>& result,int depth){
if(cur==nullptr) return;
if(result.size()==depth) result.push_back(vector<int>());
result[depth].push_back(cur->val);
order(cur->left,result,depth+1);
order(cur->right,result,depth+1);
}
vector<vector<int>> levelOrder(TreeNode* root){
vector<vector<int>> result;
int depth=0;
order(root,result,depth);
return result;
}
};
翻转二叉树
class Solution{
public:
TreeNode* invertTree(TreeNode* root){
if(root==NULL) return root;
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
class Solution{
public:
TreeNode* invertTree(TreeNode* root){
if(root==NULL) return root;
stack<Treeode*> st;
st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
st.pop();
swap(node->left,node->right);
if(node->right) st.push(node->right);
if(node->left) st.push(node->left);
}
return root;
}
}
class Solution{
public:
TreeNode* invertTree(TreeNode* root){
queue<TreeNode*> que;
if(root!=NULL) que.push(root);
while(!que.empty()){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode* cur=st.top();
st.pop();
swap(cur->left,cur->right);
if(cur->left) st.push(cur->left);
if(cur->right) st.push(cur->right);
}
}
return root;
}
}
对称二叉树
class Solution{
public:
bool compare(TreeNode* left,TreeNode* right){
if(left==NULL&&right!=NULL) return false;
else if(left!=NULL&&right==NULL) return false;
else if(left==NULL&&right==NULL) return true;
else if(left->val!=right->val) return false;
bool outside=compare(left->left,right->right);
bool inside=compare(left->right,right->left);
bool isSame=outside&&inside;
return isSame;
}
bool isSymmetric(TreeNode* root){
if(root==NULL) return true;
return compare(root->left,root->right);
}
}
//迭代法 层序遍历
class Solution{
public:
bool isSymmetric(TreeNode* root){
if(root==NUlL) return true;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while(!que.empty()){
TreeNode* leftNode=que.front();que.pop();
TreeNode* rightNode=que.front();que.pop();
if(!leftNode&&!rightNode){
continue;
}
if(!leftNode||!rightNode||(leftNode->val!=rightNode->val))){
return false;
}
que.push(leftNode->left);
que.push(rightNode->right);
que.push(leftNode->right);
que.push(rightNode->left);
}
return true;
}
}
二叉树的最大深度
//递归法
class Solution{
public:
int getdepth(TreeNode* node){
if(node==NULL) return 0;
int leftdepth=getdepth(node->left);
int rightdepth=getdepth(node->right);
int depth=max(leftdepth,rightdepth)+1;
return depth;
}
int maxdepth(TreeNode* root){
return getdepth(root);
}
};
//迭代法 层序遍历
class Solution{
public:
int maxdepth(TreeNode* root){
if(root==NULL) return 0;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size=que.size();
depth++;
for(int i=0;i<size();i++){
TreeNode* cur=que.top();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return depth;
}
}
二叉树的最小深度
class Solution{
public:
int getDepth(TreeNode* node){
if(node==NULL) return 0;
int leftdepth=getDepth(node->left);
int rightdepth=getDepth(node->right);
if(node->left==NULL&&node->right!=NULL){
return 1+rightdepth;
}
if(node->left!=NULL&&node->right==NULL){
return 1+leftdepth;
}
return 1+min(rightdepth,leftdepth);
}
int minDepth(TreeNode* root){
return getDepth(root);
}
}
//迭代法 层序遍历
class Solution{
public:
int maxdepth(TreeNode* root){
if(root==NULL) return 0;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()){
int size=que.size();
depth++;
for(int i=0;i<size();i++){
TreeNode* cur=que.top();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
if(!node->left&&!node->right){
return depth;
}
}
}
return depth;
}
}
完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
//利用完全二叉树特性
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftHeight = 0, rightHeight = 0; // 这里初始为0是有目的的,为了下面求指数方便
while (left) { // 求左子树深度
left = left->left;
leftHeight++;
}
while (right) { // 求右子树深度
right = right->right;
rightHeight++;
}
if (leftHeight == rightHeight) {
return (2 << leftHeight) - 1; // 注意(2<<1) 相当于2^2,所以leftHeight初始为0
}
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
class Solution {
public:
int getHeight(TreeNode* node){
if(node==NULL) return 0;
int leftHeight=getHeight(node->left);
if(leftHeight==-1) return -1;
int rightHeight=getHeight(node->right);
if(rightHeight==-1) return -1;
int result;
if(abs(leftHeight-rightHeight)>1){
return -1;
}else{
return 1+max(leftHeight,rightHeight);
}
return result;
}
bool isBalanced(TreeNode* root) {
return getHeight(root)==-1?false:true;
}
};
二叉树的所有路径
给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
class Solution {
private:
void traversal(TreeNode* cur,string path,vector<string>& result){
path+=to_string(cur->val);
if(cur->left==NULL&&cur->right==NULL){
result.push_back(path);
}
if(cur->left) traversal(cur->left,path+"->",result);
if(cur->right) traversal(cur->right,path+"->",result);
}
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
string path;
if(root==NULL) return result;
traversal(root,path,result);
return result;
}
};
左叶子之和
给定二叉树的根节点 root ,返回所有左叶子之和。
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root==NULL) return 0;
int leftValue=sumOfLeftLeaves(root->left);
int rightValue=sumOfLeftLeaves(root->right);
int midValue=0;
if(root->left!=NULL&&root->left->left==NULL&&root->left->right==NULL){
midValue=root->left->val;
}
int sum=midValue+leftValue+rightValue;
return sum;
}
};
找树左下角的值
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if(root!=NULL) que.push(root);
int result=0;
while(!que.empty()){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode* cur=que.front();
que.pop();
if(i==0) result=cur->val;
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return result;
}
};
路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
class solution {
private:
bool traversal(treenode* cur, int count) {
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回
if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true;
count += cur->left->val; // 回溯,撤销处理结果
}
if (cur->right) { // 右
count -= cur->right->val; // 递归,处理节点;
if (traversal(cur->right, count)) return true;
count += cur->right->val; // 回溯,撤销处理结果
}
return false;
}
public:
bool haspathsum(treenode* root, int sum) {
if (root == null) return false;
return traversal(root, sum - root->val);
}
};
//简洁写法
class solution {
public:
bool haspathsum(treenode* root, int sum) {
if (root == null) return false;
if (!root->left && !root->right && sum == root->val) {
return true;
}
return haspathsum(root->left, sum - root->val) || haspathsum(root->right, sum - root->val);
}
};
从中序与后序遍历序列构造二叉树
class Solution {
public:
TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size()==0) return NULL;
int rootValue=postorder[postorder.size()-1];
TreeNode* root=new TreeNode(rootValue);
if(postorder.size()==1) return root;
int delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++){
if(inorder[delimiterIndex]==rootValue) break;
}
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
postorder.resize(postorder.size()-1);
vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
root->left = traversal(leftInorder, leftPostorder);
root->right = traversal(rightInorder, rightPostorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder){
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
return traversal(inorder, postorder);
}
};
class Solution {
private:
// 中序区间:[inorderBegin, inorderEnd),后序区间[postorderBegin, postorderEnd)
TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& postorder, int postorderBegin, int postorderEnd) {
if (postorderBegin == postorderEnd) return NULL;
int rootValue = postorder[postorderEnd - 1];
TreeNode* root = new TreeNode(rootValue);
if (postorderEnd - postorderBegin == 1) return root;
int delimiterIndex;
for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue) break;
}
// 切割中序数组
// 左中序区间,左闭右开[leftInorderBegin, leftInorderEnd)
int leftInorderBegin = inorderBegin;
int leftInorderEnd = delimiterIndex;
// 右中序区间,左闭右开[rightInorderBegin, rightInorderEnd)
int rightInorderBegin = delimiterIndex + 1;
int rightInorderEnd = inorderEnd;
// 切割后序数组
// 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
int leftPostorderBegin = postorderBegin;
int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 终止位置是 需要加上 中序区间的大小size
// 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);
int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了
root->left = traversal(inorder, leftInorderBegin, leftInorderEnd, postorder, leftPostorderBegin, leftPostorderEnd);
root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);
return root;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
// 左闭右开的原则
return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());
}
};
最大二叉树
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
class Solution {
public:
TreeNode* traversal(vector<int>& nums,int left,int right){
if(left>=right) return nullptr;
int maxValueIndex=left;
for(int i=left+1;i<right;i++){
if(nums[i]>nums[maxValueIndex]) maxValueIndex=i;
}
TreeNode* root=new TreeNode(nums[maxValueIndex]);
root->left=traversal(nums,left,maxValueIndex);
root->right=traversal(nums,maxValueIndex+1,right);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return traversal(nums,0,nums.size());
}
};
合并两个二叉树
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==NULL) return root2;
if(root2==NULL) return root1;
TreeNode* root=new TreeNode(0);
root->val=root1->val+root2->val;
root->left=mergeTrees(root1->left,root2->left);
root->right=mergeTrees(root1->right,root2->right);
return root;
}
};
二叉搜索树中的搜索
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
//递归
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;
}
};
//迭代
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while(root!=NULL){
if(root->val>val) root=root->left;
else if(root->val<val) root=root->right;
else return root;
}
return NULL;
}
};
验证二叉搜索树
//递归
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;
}
};
//迭代
class Solution {
public:
bool isValidBST(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = NULL; // 记录前一个节点
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->left; // 左
} else {
cur = st.top(); // 中
st.pop();
if (pre != NULL && cur->val <= pre->val)
return false;
pre = cur; //保存前一个访问的结点
cur = cur->right; // 右
}
}
return true;
}
};
二叉搜索树的最小绝对差
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
//递归
class Solution {
private:
int result=INT_MAX;
TreeNode* pre;
void traversal(TreeNode* cur){
if(cur==NULL) return;
traversal(cur->left);
if(pre!=NULL){
result=min(result,cur->val-pre->val);
}
pre=cur;
traversal(cur->right);
}
public:
int getMinimumDifference(TreeNode* root) {
traversal(root);
return result;
}
};
//迭代
class Solution {
public:
int getMinimumDifference(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur=root;
TreeNode* pre=NULL;
int result=INT_MAX;
while(cur!=NULL||!st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->left;
}else{
cur=st.top();
st.pop();
if(pre!=NULL){
result=min(result,cur->val-pre->val);
}
pre=cur;
cur=cur->right;
}
}
return result;
}
};
二叉搜索树中的众数
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树
//递归
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.push_back(cur->val);
}
if(count>maxCount){
maxCount=count;
result.clear();
result.push_back(cur->val);
}
searchBST(cur->right);
return;
}
public:
vector<int> findMode(TreeNode* root) {
maxCount=0;
count=0;
pre=NULL;
result.clear();
searchBST(root);
return result;
}
};
//迭代
class Solution {
public:
vector<int> findMode(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = NULL;
int maxCount = 0; // 最大频率
int count = 0; // 统计频率
vector<int> result;
while (cur != NULL || !st.empty()) {
if (cur != NULL) { // 指针来访问节点,访问到最底层
st.push(cur); // 将访问的节点放进栈
cur = cur->left; // 左
} else {
cur = st.top();
st.pop(); // 中
if (pre == NULL) { // 第一个节点
count = 1;
} else if (pre->val == cur->val) { // 与前一个节点数值相同
count++;
} else { // 与前一个节点数值不同
count = 1;
}
if (count == maxCount) { // 如果和最大值相同,放进result中
result.push_back(cur->val);
}
if (count > maxCount) { // 如果计数大于最大值频率
maxCount = count; // 更新最大频率
result.clear(); // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
result.push_back(cur->val);
}
pre = cur;
cur = cur->right; // 右
}
}
return result;
}
};
公共祖先问题
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==q||root==p||root==NULL) return root;
TreeNode* left=lowestCommonAncestor(root->left,p,q);
TreeNode* right=lowestCommonAncestor(root->right,p,q);
if(left!=NULL&&right!=NULL) return root;
if(left==NULL&&right!=NULL) return right;
else if(left!=NULL&&right==NULL) return left;
else{
return NULL;
}
}
};
二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
class Solution {
private:
TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) {
if (cur == NULL) return cur;
// 中
if (cur->val > p->val && cur->val > q->val) { // 左
TreeNode* left = traversal(cur->left, p, q);
if (left != NULL) {
return left;
}
}
if (cur->val < p->val && cur->val < q->val) { // 右
TreeNode* right = traversal(cur->right, p, q);
if (right != NULL) {
return right;
}
}
return cur;
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return traversal(root, p, q);
}
};
二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root==NULL){
TreeNode* node=new TreeNode(val);
return node;
}
if(root->val>val) root->left=insertIntoBST(root->left,val);
if(root->val<val) root->right=insertIntoBST(root->right,val);
return root;
}
};
删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
if (root->val == key) {
// 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
if (root->left == nullptr && root->right == nullptr) {
///! 内存释放
delete root;
return nullptr;
}
// 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
else if (root->left == nullptr) {
auto retNode = root->right;
///! 内存释放
delete root;
return retNode;
}
// 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
else if (root->right == nullptr) {
auto retNode = root->left;
///! 内存释放
delete root;
return retNode;
}
// 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
// 并返回删除节点右孩子为新的根节点。
else {
TreeNode* cur = root->right; // 找右子树最左面的节点
while(cur->left != nullptr) {
cur = cur->left;
}
cur->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置
TreeNode* tmp = root; // 把root节点保存一下,下面来删除
root = root->right; // 返回旧root的右孩子作为新root
delete tmp; // 释放节点内存(这里不写也可以,但C++最好手动释放一下吧)
return root;
}
}
if (root->val > key) root->left = deleteNode(root->left, key);
if (root->val < key) root->right = deleteNode(root->right, key);
return root;
}
};
修建二叉搜索树
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root==NULL) return NULL;
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;
}
};
构造二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
class Solution {
private:
TreeNode* traversal(vector<int>& nums,int left,int right){
if(left>right) return NULL;
int mid=left+(right-left)/2;
TreeNode* root=new TreeNode(nums[mid]);
root->left=traversal(nums,left,mid-1);
root->right=traversal(nums,mid+1,right);
return root;
}
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root=traversal(nums,0,nums.size()-1);
return root;
}
};
搜索树转成累加树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键 小于 节点键的节点。
节点的右子树仅包含键 大于 节点键的节点。
左右子树也必须是二叉搜索树。
class Solution {
private:
int pre;
void traversal(TreeNode* cur){
if(cur==NULL) return;
traversal(cur->right);
cur->val+=pre;
pre=cur->val;
traversal(cur->left);
}
public:
TreeNode* convertBST(TreeNode* root) {
pre=0;
traversal(root);
return root;
}
};