二叉树
- 二叉树理论基础
- 二叉树的递归遍历
- 二叉树的迭代遍历(统一写法:加空指针)
- 二叉树的层序遍历
- 迭代法
- 二叉树的层序遍历II
- 二叉树的右视图
- N叉树的层序遍历
- 填充每个节点的下一个右侧节点指针
- 二叉树的最大深度
- 层序遍历法(迭代)
- 后序遍历法(递归)
- 二叉树的最小深度
- 层序遍历法
- 后序遍历法
- 翻转二叉树
- 完全二叉树的节点个数
- 迭代法
- 平衡二叉树
- 二叉树的所有路径
- 左叶子之和
- 找树左下角的值
- 路径总和
- 递归法
- 迭代法
- 从中序和后序遍历序列构造二叉树
- 版本一
- 版本二
- 最大二叉树
- 合并二叉树
- 递归法
- 迭代法
- 二叉搜索树中的搜索
- 递归法
- 验证二叉搜索树
- 递归法
- 迭代法
- 二叉搜索树的最小绝对差
- 二叉搜索树中的众数
- 递归法
- 迭代法
- 二叉树的最近公共祖先
- 二叉搜索树的最近公共祖先
- 二叉搜索树中的插入操作
- 迭代法
- 删除二叉搜索树中的节点
- 递归法
- 迭代法
- 修剪二叉搜索树
- 递归法
- 迭代法
- 将有序数组转换为二叉搜索树
- 递归法
- 二叉搜索树总结
二叉树理论基础
二叉树的递归遍历
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* l, TreeNode* r) :val(x), left(l), right(r){}
};
//前序遍历:中左右
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == nullptr) {
return;
}
vec.push_back(cur->val);
traversal(cur->left, vec);
traversal(cur->right, vec);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root, res);
return res;
}
};
//中序遍历:左中右
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == nullptr) {
return;
}
traversal(cur->left, vec);
vec.push_back(cur->val);
traversal(cur->right, vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root, res);
return res;
}
};
//后序遍历:左右中
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == nullptr) {
return;
}
traversal(cur->left, vec);
traversal(cur->right, vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
traversal(root, res);
return res;
}
};
二叉树的迭代遍历(统一写法:加空指针)
//节点
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* l, TreeNode* r) :val(x), left(l), right(r){}
};
//前序遍历:中左右
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (root != nullptr)st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != nullptr) {
st.pop();
if (node->right)st.push(node->right);
if (node->left)st.push(node->left);
st.push(node);
st.push(nullptr);
}
else {
st.pop();
node = st.top();
st.pop();
res.push_back(node->val);
}
}
return res;
}
};
//中序遍历:左中右
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
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); //stack先存右孩子节点
st.push(node);
st.push(nullptr);
if (node->left)st.push(node->left);
}
else { //只有遇到空节点才会处理节点的下一个节点
st.pop();
node = st.top();
st.pop();
res.push_back(node->val);
}
}
return res;
}
};
//后序遍历:左右中
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (root != nullptr)st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != nullptr) {
st.pop();
st.push(node);
st.push(nullptr);
if (node->right)st.push(node->right);
if (node->left)st.push(node->left);
}
else {
st.pop();
node = st.top();
st.pop();
res.push_back(node->val);
}
}
return res;
}
};
二叉树的层序遍历
迭代法
class Solution{
public:
vector<vector<int> > levelOrder(TreeNode* root){
queue<TreeNode*> que;
vector<vector<int> > ans;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> temp;
for(int i =0;i<size;i++){
TreeNode* p = que.front();
que.pop();
temp.push_back(p->val);
if(p->left!=nullptr) que.push(p->left);
if(p->right!=nullptr) que.push(p->right);
}
ans.push_back(temp);
}
return ans;
}
};
二叉树的层序遍历II
力扣题目链接
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int> > result;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> res;
for(int i =0;i<size;i++){
TreeNode* node = que.front();
que.pop();
res.push_back(node->val);
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
result.push_back(res);
}
reverse(result.begin(),result.end());
return result;
}
};
二叉树的右视图
力扣题目链接
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*> que;
vector<int> result;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> res;
for(int i =0;i<size;i++){
TreeNode* node = que.front();
que.pop();
if(i==size-1){
result.push_back(node->val);
}
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
}
return result;
}
};
N叉树的层序遍历
力扣题目链接
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
queue<Node*> que;
vector<vector<int> > result;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
vector<int> res;
for(int i =0;i<size;i++)
{
Node* node = que.front();
que.pop();
res.push_back(node->val);
for(int j =0;j<node->children.size();j++)
{
if(node->children[j])que.push(node->children[j]);
}
}
result.push_back(res);
}
return result;
}
};
填充每个节点的下一个右侧节点指针
class Solution {
public:
Node* connect(Node* root) {
queue<Node*> que;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
Node* pre;
Node* cur;
for(int i =0;i<size;i++)
{
cur = que.front();
if(i==0){
pre = que.front();
}
else if(0<i<size-1){
pre->next = cur;
pre = cur;
}
else{
pre->next = cur;
pre = cur;
pre->next = nullptr;
}
que.pop();
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return root;
}
};
二叉树的最大深度
前序遍历求深度,后序遍历求高度
层序遍历法(迭代)
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL) return 0;
int depth = 0;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
int size = que.size();
depth++; // 记录深度
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return depth;
}
};
后序遍历法(递归)
后序遍历法求的是二叉树的根节点高度,而根节点高度同样也是二叉树的最大深度。
class Solution {
public:
int posttraversal(TreeNode* node,int depth){
if(node==nullptr){
return 0;
}
int leftdepth = posttraversal(node->left,depth);
int rightdepth = posttraversal(node->right,depth);
return 1+max(leftdepth,rightdepth);
}
int maxDepth(TreeNode* root) {
int depth = 1; //leetcode都以节点为一度
return posttraversal(root,depth);
}
};
二叉树的最小深度
力扣题目链接
层序遍历法
只有当左右孩子都为空的时候,才能说明遍历的最低点了,如果其中一个孩子为空则不是最低点。
class Solution {
public:
int minDepth(TreeNode* root) {
int depth=0;
queue<TreeNode*> que;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
for(int i =0;i<size;i++){
TreeNode* node = que.front();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
if(!node->left && !node->right) return depth+1;
}
depth++;
}
return depth;
}
};
后序遍历法
用后序遍历法的时候要注意这样一个问题:
如果左子树为空,右子树不为空,则最小深度是1+右子树的深度
如果右子树为空,左子树不为空,则最小深度是1+左子树的深度
如果左右子树都不为空,则最小深度是1+min(左子树深度,右子树深度)
class Solution {
public:
int posttraversal(TreeNode* node,int depth){
if(node==nullptr){
return 0;
}
int leftdepth = posttraversal(node->left,depth);
int rightdepth = posttraversal(node->right,depth);
if(node->left!=nullptr && node->right==nullptr){
return 1+leftdepth;
}
else if(node->right!=nullptr && node->left==nullptr){
return 1+rightdepth;
}
else{
return 1+min(leftdepth,rightdepth);
}
}
int minDepth(TreeNode* root) {
int depth=1;
return posttraversal(root,depth);
}
};
翻转二叉树
力扣题目链接
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
queue<TreeNode*> que;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size = que.size();
for(int i =0;i<size;i++){
TreeNode* node = que.front();
que.pop();
TreeNode* temp = node->left;
node->left = node->right;
node->right = temp;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return root;
}
};
完全二叉树的节点个数
力扣题目链接
完全二叉树只有两种情况:(1)满二叉树(2)最后一层叶子节点没有铺满
对于情况(1),可以直接用2^树深度-1来计算,此时根节点的深度为1
对于情况(2),分别递归其左孩子节点和右孩子节点,递归到某一深度,一定有左孩子或者有孩子为满二叉树,然后可以按照情况1计算。
迭代法
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftDepth = 1, rightDepth = 1; // 这里初始为0是有目的的,为了下面求指数方便
while (left) { // 求左子树深度
left = left->left;
leftDepth++;
}
while (right) { // 求右子树深度
right = right->right;
rightDepth++;
}
if (leftDepth == rightDepth) {
return pow(2,leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
}
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
平衡二叉树
class Solution {
public:
//求某一个节点的高度,左右中后序遍历。
int getHeight(TreeNode* node){
if(node==nullptr){
return 0;
}
int leftheight = getHeight(node->left);
int rightheight = getHeight(node->right);
return max(leftheight,rightheight)+1;
}
bool isBalanced(TreeNode* node){
if(node==nullptr){
return true;
}
//先判断左右子树分别是不是平衡二叉树,如果有一个不是,则整体一定不是,相当于运算中的剪枝。
bool left = isBalanced(node->left);
bool right = isBalanced(node->right);
if(left==false||right==false){
return false;
}
//如果左右子树都是,则判断根节点是否满足平衡二叉树条件。
int leftheight = getHeight(node->left);
int rightheight = getHeight(node->right);
if(abs(leftheight-rightheight)<=1) return true;
else return false;
}
};
二叉树的所有路径
力扣题目链接
class Solution {
public:
// 前序遍历:中左右(递归加回溯)
void traversal(TreeNode* node,vector<int>& path,vector<string>& res)
{
//中:先中是因为之后的停止条件是要处理叶子节点的,而这个叶子节点是要在中的步骤里先被添加到path里
path.push_back(node->val);
if(node->left==nullptr && node->right==nullptr){
string str;
for(int i =0;i<path.size()-1;i++){
str+= to_string(path[i]);
str+="->";
}
str+=to_string(path[path.size()-1]);
res.push_back(str);
}
//左
if(node->left){
traversal(node->left,path,res);
path.pop_back(); //回溯
}
//右
if(node->right){
traversal(node->right,path,res);
path.pop_back(); //回溯
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
vector<int> path;
traversal(root,path,res);
return res;
}
};
左叶子之和
力扣题目链接
class Solution {
public:
int traversal(TreeNode* node, int & res){
if(node==nullptr){
return res;
}
if(node->left) traversal(node->left,res);
if(node->right) traversal(node->right,res);
if(node->left!=nullptr && node->left->left==nullptr && node->left->right==nullptr){
res+=node->left->val;
return res;
}else{
return res;
}
}
int sumOfLeftLeaves(TreeNode* root) {
int res=0;
return traversal(root,res);
}
};
找树左下角的值
力扣题目链接
使用前序遍历(中序,后序都可以),保证优先搜索左边,并且记录深度最大的叶子节点,此时就是树的最后一行最左边的值
class Solution {
public:
int maxDepth = INT_MIN;
int res;
void traversal(TreeNode* node,int depth){
if(node->left==nullptr && node->right==nullptr){
if(depth>maxDepth){
maxDepth = depth;
res = node->val;
}
}
//中:不处理节点
//左:
if(node->left){
depth++;
traversal(node->left,depth);
depth--;
}
if(node->right){
depth++;
traversal(node->right,depth);
depth--;
}
return ;
}
int findBottomLeftValue(TreeNode* root) {
int depth = 1;
traversal(root,depth);
return res;
}
};
路径总和
递归法
class Solution {
public:
bool traversal(TreeNode* node,int count){
// 截止条件
if(!node->left && !node->right){
if(count==0) return true;
else return false;
}
// 中
// 左
if(node->left){
count-=node->left->val;
if(traversal(node->left,count)) return true;
count+=node->left->val;
}
//右
if(node->right){
count-=node->right->val;
if(traversal(node->right,count)) return true;
count+=node->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root) return traversal(root,targetSum-root->val);
else return false;
}
};
迭代法
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
stack<pair<TreeNode*,int> > st;
st.push({root,root->val});
while(!st.empty()){
auto temp = st.top();
st.pop();
TreeNode* node = temp.first;
if(!node->left && !node->right){
if(targetSum==temp.second) return true;
}
if(node->right){
st.push({node->right,temp.second+node->right->val});
}
if(node->left){
st.push({node->left,temp.second+node->left->val});
}
}
return false;
}
};
从中序和后序遍历序列构造二叉树
- 如果数组大小(后序遍历数组,前序也可以)为零,说明是空节点了。
- 如果不为空,那么取后序数组最后一个元素作为节点元素
- 找到后序数组最后一个元素再中序数组的位置,作为切割点
- 切割中序数组,切成中序左数组和中序右数组(一定要先切中序数组)
- 切割后序数组,切成后序左数组和后序右数组
- 递归处理左区间和右区间
版本一
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
//1.如果数组大小为零,说明是空节点
if(postorder.size()==0) return nullptr;
//2.(1)后序遍历数组最后一个元素,就是当前的中间节点
int rootvalue = postorder[postorder.size()-1];
TreeNode* root = new TreeNode(rootvalue);
//2.(2)如果是叶子节点
if(postorder.size()==1) return root;
//3.(1)寻找切割点
int delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size()-1;delimiterIndex++){
if(inorder[delimiterIndex]==rootvalue) break;
}
//3.(2)割掉后序数组最后一个节点
postorder.resize(postorder.size()-1);
//4.切割中序数组,得到中序左数组和中序右数组
//左闭右开区间
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
//5.切割后序数组,得到后序左数组和后序右数组
vector<int> leftpostorder(postorder.begin(),postorder.begin()+leftInorder.size());
vector<int> rightpostorder(postorder.begin()+leftInorder.size(),postorder.end());
//6.递归处理左右区间
root->left = buildTree(leftInorder,leftpostorder);
root->right = buildTree(rightInorder,rightpostorder);
return root;
}
};
版本二
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());
}
};
最大二叉树
力扣题目链接
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
//1.如果为空返回空指针
if(nums.size()==0){
return nullptr;
}
//2.如果不为空
int maxPosition = max_element(nums.begin(),nums.end())-nums.begin();
TreeNode* root = new TreeNode(nums[maxPosition]);
//3.分割数组
vector<int> leftorder(nums.begin(),nums.begin()+maxPosition);
vector<int> rightorder(nums.begin()+maxPosition+1,nums.end());
root->left = constructMaximumBinaryTree(leftorder);
root->right = constructMaximumBinaryTree(rightorder);
return root;
}
};
合并二叉树
力扣题目链接
递归法
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr) return root2;
if(root2==nullptr) return root1;
root1->val += root2->val;
root1->left = mergeTrees(root1->left,root2->left);
root1->right = mergeTrees(root1->right,root2->right);
return root1;
}
};
迭代法
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(t1==nullptr) return t2;
if(t2==nullptr) return t1;
queue<TreeNode*> que;
que.push(t1);
que.push(t2);
while(!que.empty()){
TreeNode* node1 = que.front();
que.pop();
TreeNode* node2 = que.front();
que.pop();
node1->val+=node2->val;
if(node1->left!=nullptr && node2->left!=nullptr){
que.push(node1->left);
que.push(node2->left);
}
if(node1->right!=nullptr && node2->right!=nullptr){
que.push(node1->right);
que.push(node2->right);
}
if(node1->left==nullptr && node2->left!=nullptr){
node1->left = node2->left;
}
if(node1->right==nullptr && node2->right!=nullptr){
node1->right = node2->right;
}
}
return t1;
}
};
二叉搜索树中的搜索
力扣题目链接
递归法
class Solution {
public:
int value;
TreeNode* traversal(TreeNode* node){
if(node==nullptr){
return nullptr;
}
TreeNode* n;
if(value>node->val){
n = traversal(node->right);
}
else if(value<node->val){
n = traversal(node->left);
}
else{
return node;
}
return n;
}
TreeNode* searchBST(TreeNode* root, int val) {
value = val;
return traversal(root);
}
};
验证二叉搜索树
递归法
class Solution {
public:
TreeNode* pre = nullptr;
bool isValidBST(TreeNode* root) {
if(root==nullptr) return true;
bool left = isValidBST(root->left);
if(pre!=nullptr && pre->val>root->val) return false;
else pre = root;
bool right = isValidBST(root->right);
return left && right;
}
};
迭代法
二叉树的中序遍历
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(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
st.pop();
result.push_back(cur->val); // 中
cur = cur->right; // 右
}
}
return result;
}
};
class Solution {
public:
bool isValidBST(TreeNode* root) {
if(root==nullptr) return true;
stack<TreeNode*> st;
TreeNode* pre = nullptr;
TreeNode* cur = root;
while(cur!=nullptr || !st.empty()){
if(cur!=nullptr){
st.push(cur);
cur=cur->left; //左
}
else{
cur = st.top();
st.pop();
if(pre!=nullptr && pre->val>=cur->val) return false;
else pre = cur;
cur = cur->right;
}
}
return true;
}
};
二叉搜索树的最小绝对差
class Solution {
public:
int getMinimumDifference(TreeNode* root) {
if(root==nullptr) return 0;
stack<TreeNode*> st;
TreeNode* pre = nullptr;
TreeNode* cur = root;
int ans = INT_MAX;
while(cur!=nullptr || !st.empty()){
if(cur!=nullptr){
st.push(cur);
cur=cur->left;
}
else{
cur = st.top();
st.pop();
if(pre!=nullptr&&abs(cur->val-pre->val)<ans){
ans = abs(cur->val-pre->val);
}
pre = cur;
cur = cur->right;
}
}
return ans;
}
};
二叉搜索树中的众数
递归法
class Solution {
public:
unordered_map<int,int> map;
bool static cmp(const pair<int,int>&a,const pair<int,int>&b){
return a.second>b.second;
}
void traversal(TreeNode* node){
if(node==nullptr){
return;
}
if(node->left) traversal(node->left);
map[node->val]++;
if(node->right) traversal(node->right);
}
vector<int> findMode(TreeNode* root) {
vector<int> res;
if(root==nullptr) return res;
traversal(root);
vector<pair<int,int> > vec(map.begin(),map.end());
sort(vec.begin(),vec.end(),cmp);
res.push_back(vec[0].first);
for(int i =1;i<vec.size();i++)
{
if(vec[i].second==vec[0].second) res.push_back(vec[i].first);
else break;
}
return res;
}
};
迭代法
class Solution {
public:
vector<int> findMode(TreeNode* root) {
vector<int> vec;
int num=0,count=0,count_max=0;
stack<TreeNode*> st;
if(root==nullptr) return vec;
TreeNode* pre = nullptr;
TreeNode* cur = root;
while(cur!=nullptr || !st.empty()){
if(cur!=nullptr){
st.push(cur);
cur = cur->left;
}
else{
cur = st.top();
st.pop();
if(pre==nullptr) count=1;
else if(pre->val==cur->val) count++;
else count = 1;
if(count==count_max){
vec.push_back(cur->val);
}
else if(count>count_max){
vec.clear();
vec.push_back(cur->val);
count_max = count;
}
pre = cur;
cur = cur->right;
}
}
return vec;
}
};
二叉树的最近公共祖先
class Solution {
public:
TreeNode* traversal(TreeNode* node,TreeNode* p, TreeNode* q){
if(node==p || node==q || node==nullptr) return node;
TreeNode* left = traversal(node->left,p,q);
TreeNode* right = traversal(node->right,p,q);
if(left!=nullptr && right!=nullptr) return node;
else if(left!=nullptr && right==nullptr) return left;
else if(right!=nullptr && left==nullptr) return right;
else return nullptr;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return traversal(root,p,q);
}
};
二叉搜索树的最近公共祖先
class Solution {
public:
TreeNode* ans=nullptr;
int a,b;
void traversal(TreeNode* node){
if(node==nullptr){
return;
}
if(node->val>=a && node->val<=b) {
ans = node;
return;
}
if(node->left) traversal(node->left);
if(node->right) traversal(node->right);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(p->val<q->val){
a = p->val;
b = q->val;
}else{
a = q->val;
b = p->val;
}
if(root==nullptr) return ans;
else{
traversal(root);
return ans;
}
}
};
二叉搜索树中的插入操作
class Solution {
public:
void traversal(TreeNode* node, int val){
if(node==nullptr){
return;
}
if(node->val>val){
if(node->left!=nullptr) traversal(node->left,val);
else{
node->left = new TreeNode(val);
}
return;
}
else{
if(node->right!=nullptr) traversal(node->right,val);
else{
node->right = new TreeNode(val);
}
return ;
}
}
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root==nullptr){
root = new TreeNode(val);
}
else traversal(root,val);
return root;
}
};
迭代法
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == NULL) {
TreeNode* node = new TreeNode(val);
return node;
}
TreeNode* cur = root;
TreeNode* parent = root; // 这个很重要,需要记录上一个节点,否则无法赋值新节点
while (cur != NULL) {
parent = cur;
if (cur->val > val) cur = cur->left;
else cur = cur->right;
}
TreeNode* node = new TreeNode(val);
if (val < parent->val) parent->left = node;// 此时是用parent节点的进行赋值
else parent->right = node;
return root;
}
};
删除二叉搜索树中的节点
- 没找到删除的节点,遍历到空节点就直接返回
- 左右孩子都为空(叶子节点),直接删除节点,返回NULL为根节点。
- 删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
- 删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
- 左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点左右孩子为新的根节点
情况五:
递归法
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
//情况一
if(root==nullptr) return root;
//情况二
if(root->val == key){
if(root->left==nullptr && root->right ==nullptr){
//使用delete来删除节点,释放内存
delete root;
return nullptr;
}
//情况三
else if(root->left ==nullptr){
if(root->right!=nullptr){
TreeNode* node = root->right;
delete root;
return node;
}
}
// 情况四
else if(root->right ==nullptr){
if(root->left!=nullptr){
TreeNode* node = root->left;
delete root;
return node;
}
}
else{
TreeNode* cur = root->right;
while(cur->left!=nullptr){
cur = cur->left;
}
cur->left = root->left;
TreeNode* node1 = root;
root = root->right;
delete node1;
return root;
}
}
if(root->left) root->left = deleteNode(root->left,key);
if(root->right) root->right = deleteNode(root->right,key);
return root;
}
};
迭代法
class Solution {
private:
TreeNode* deleteOneNode(TreeNode* target){
if(target == nullptr) return target;
if(target->right==nullptr) return target->left;
TreeNode* cur = target->right;
while(cur->left){
cur = cur->left;
}
cur->left = target->left;
return target->right;
}
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(root==nullptr) return nullptr;
TreeNode* cur=root;
TreeNode* pre=nullptr;
while(cur){
if(cur->val == key) break;
pre = cur;
if(cur->val>key) cur = cur->left;
if(cur->val<key) cur = cur->right;
}
if(pre==nullptr){
return nullptr;
}
if(pre->left->val==key && pre->left){
pre->left = deleteOneNode(cur);
}
if(pre->right->val==key && pre->right){
pre->right = deleteOneNode(cur);
}
return root;
}
};
修剪二叉搜索树
递归法
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;
}
};
迭代法
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int L, int R) {
if (!root) return nullptr;
// 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭
while (root != nullptr && (root->val < L || root->val > R)) {
if (root->val < L) root = root->right; // 小于L往右走
else root = root->left; // 大于R往左走
}
TreeNode *cur = root;
// 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况
while (cur != nullptr) {
while (cur->left && cur->left->val < L) {
cur->left = cur->left->right;
}
cur = cur->left;
}
cur = root;
// 此时root已经在[L, R] 范围内,处理右孩子大于R的情况
while (cur != nullptr) {
while (cur->right && cur->right->val > R) {
cur->right = cur->right->left;
}
cur = cur->right;
}
return root;
}
};
将有序数组转换为二叉搜索树
递归法
class Solution {
public:
TreeNode* traversal(TreeNode* root,int left,int right,vector<int>& nums)
{
if(left==right){
root = new TreeNode(nums[left]);
}
else if(left<right){
int middle = (right+left)/2;
root = new TreeNode(nums[middle]);
root->left = traversal(root->left,left,middle-1,nums);
root->right = traversal(root->right,middle+1,right,nums);
}
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = new TreeNode();
int left=0,right=nums.size()-1;
return traversal(root,left,right,nums);
}
};
二叉搜索树总结
代码随想录总结