二叉树
文章目录
- 二叉树
- 1. 二叉树的递归遍历
- 144.前序遍历
- 94.中序遍历
- 145.后续遍历
- *2.二叉树的迭代遍历
- 145.前序遍历
- 94.中序遍历
- 145.后续遍历
- 3.统一二叉树迭代遍历
- 144.前序遍历
- 94.中序排序
- 145.后序遍历
- 4.层序遍历
- 102.二叉树的层序遍历
- 107. 二叉树的层序遍历 II
- 199. 二叉树的右视图
- 637. 二叉树的层平均值
- 429. N 叉树的层序遍历
- 515. 在每个树行中找最大值
- 116. 填充每个节点的下一个右侧节点指针
- 117. 填充每个节点的下一个右侧节点指针 II
- 5.翻转二叉树
- 226.翻转二叉树
- 6.对称二叉树
- 101. 对称二叉树
- 100. 相同的树
- 572.另一个树的子树
- 7.二叉树的最大深度
- 104. 二叉树的最大深度
- 8.二叉树的最小深度
- 111.二叉树的最小深度
- 9.完全二叉树节点个数
- 222.完全二叉树节点个数
- *10.平衡二叉树
- 深度与高度区别:
- 11.二叉树的所有路径
- 257. 二叉树的所有路径
- 12.左叶子之和
- 404.左叶子之和
- 13.找树左下角的值
- 513.找树左下角的值
- 14.路径总和
- 112. 路径总和
- 113. 路径总和 II
- *15.从中序,后序遍历序列来构造二叉树
- 106. 从中序与后序遍历序列构造二叉树
- 105. 从前序与中序遍历序列构造二叉树
- 16.最大二叉树
- 654. 最大二叉树
- 17.合并二叉树
- 617.合并二叉树
- 18.二叉搜索树中的搜索
- 700.二叉搜索树中的搜索
- 20.验证二叉搜索树
- 98.验证二叉搜索树
- 21.二叉搜索树的最小绝对差
- 530.二叉搜索树的最小绝对差
- 22. 二叉搜索树中的众数
- 501. 二叉搜索树中的众数
- **23. 二叉搜索树的最近公共祖先
- 235. 二叉搜索树的最近公共祖先
- 24.二叉搜索树中的插入操作
- 701.二叉搜索树中的插入操作
- 25.删除二叉搜索树中的节点
- 450.删除二叉搜索树中的节点
- 26. 修剪二叉搜索树
- 669. 修剪二叉搜索树
- 27.将有序数组转换为二叉搜索树
- 108.将有序数组转换为二叉搜索树
- *28.把二叉搜索树转换为累加树
- 538.把二叉搜索树转换为累加树
二叉树可以链式存储,也可以顺序存储。
那么链式存储方式就用指针, 顺序存储的方式就是用数组。
顾名思义就是顺序存储的元素在内存是连续分布的,而链式存储则是通过指针把分布在各个地址的节点串联一起。
链式存储如图:
链式存储是大家很熟悉的一种方式,那么我们来看看如何顺序存储呢?
其实就是用数组来存储二叉树,顺序存储的方式如图:
用数组来存储二叉树如何遍历的呢?
如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。
二叉树定义
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) {}
* };
1. 二叉树的递归遍历
深度优先遍历:先往深走,遇到叶子节点再往回走
在深度优先遍历中:有三个顺序,前中后序遍历, 这三个顺序,经常搞混
记住技巧:这里前中后,其实指的就是中间节点的遍历顺序, 前中后序指的就是中间节点的位置。
递归写法技巧:
- 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
- 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
- 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
144.前序遍历
给你二叉树的根节点 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:
//前序
void traversal(TreeNode* node,vector<int>&v){
if(node == nullptr)return;
v.push_back(node->val);
traversal(node->left,v);
traversal(node->right,v);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int>v;
traversal(root,v);
return v;
}
};
94.中序遍历
给定一个二叉树的根节点 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:
void traversal(TreeNode* node,vector<int>&v){
if(node == nullptr)return;
traversal(node->left,v);
v.push_back(node->val);
traversal(node->right,v);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>v;
traversal(root,v);
return v;
}
};
145.后续遍历
给你一棵二叉树的根节点 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:
void traversal(TreeNode* node,vector<int>&v){
if(node == nullptr)return;
traversal(node->left,v);
traversal(node->right,v);
v.push_back(node->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int>v;
traversal(root,v);
return v;
}
};
*2.二叉树的迭代遍历
栈其实就是递归的一种实现结构,也就说前中后序遍历的逻辑其实都是可以借助栈使用非递归的方式来实现的。
145.前序遍历
/**
* 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:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
TreeNode* curNode;
vector<int>v;
if(root == nullptr)return v;
st.push(root);
while(!st.empty()){
curNode = st.top();
st.pop();
v.push_back(curNode->val);
if(curNode->right)st.push(curNode->right);
if(curNode->left)st.push(curNode->left);
}
return v;
}
};
94.中序遍历
/**
* 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:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
TreeNode* curNode;
vector<int>v;
if(root == nullptr)return v;
curNode = root;
while(!st.empty() || curNode != nullptr){
while(curNode){
st.push(curNode);
curNode = curNode->left;
}
v.push_back(st.top()->val);
curNode = st.top();
st.pop();
curNode = curNode->right;
}
return v;
}
};
145.后续遍历
/**
* 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:
//前序遍历中左右-》中右左-》反转-》左右中:后序
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
TreeNode* curNode;
vector<int>v;
if(root == nullptr)return v;
st.push(root);
while(!st.empty()){
curNode = st.top();
v.push_back(st.top()->val);
st.pop();
if(curNode->left)st.push(curNode->left);
if(curNode->right)st.push(curNode->right);
}
reverse(v.begin(),v.end());
return v;
}
};
3.统一二叉树迭代遍历
在中节点后插入一个标志,每个位置都会成为中节点,在按照顺序进行排序
自己总结一个技巧:
- 前序:先把中节点当中节点,再把左节点当中节点,再把右节点当中节点
- 中序:先把左节点当中节点,再把中节点当中节点,再把右节点当中节点
- 后序:先把左节点当中节点,再把右节点当中节点,再把中节点当中节点
144.前序遍历
/**
* 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:
vector<int> preorderTraversal(TreeNode* root) {
TreeNode* curNode;
vector<int>v;
stack<TreeNode*>st;
if(root == nullptr)return v;
st.push(root);
while(!st.empty()){
curNode = st.top();
if(curNode != nullptr){
st.pop();
if(curNode->right)st.push(curNode->right);
if(curNode->left)st.push(curNode->left);
st.push(curNode);
st.push(nullptr);
}
else{
st.pop();
curNode = st.top();
v.push_back(curNode->val);
st.pop();
}
}
return v;
}
};
94.中序排序
/**
* 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:
vector<int> inorderTraversal(TreeNode* root) {
TreeNode* curNode;
stack<TreeNode*>st;
vector<int>v;
if(root == nullptr)return v;
st.push(root);
while(!st.empty()){
curNode = st.top();
if(curNode != nullptr){
st.pop();
if(curNode->right)st.push(curNode->right);
st.push(curNode);
st.push(nullptr);
if(curNode->left)st.push(curNode->left);
}
else{
st.pop();
curNode = st.top();
v.push_back(curNode->val);
st.pop();
}
}
return v;
}
};
145.后序遍历
/**
* 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:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>v;
TreeNode* curNode;
stack<TreeNode*>st;
if(root == nullptr)return v;
st.push(root);
while(!st.empty()){
curNode = st.top();
if(curNode != nullptr){
st.push(nullptr);
if(curNode->right)st.push(curNode->right);
if(curNode->left)st.push(curNode->left);
}
else{
st.pop();
curNode = st.top();
v.push_back(curNode->val);
st.pop();
}
}
return v;
}
};
4.层序遍历
广度优先遍历:一层一层的去遍历。
广度优先遍历:层次遍历(递归法,迭代法)
广度优先遍历的实现一般使用队列来实现,这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。
102.二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
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:
void order(TreeNode* root,vector<vector<int>>& v,int depth){
if(root == nullptr)return ;
if(v.size() == depth)v.push_back(vector<int>());
v[depth].push_back(root->val);
order(root->left,v,depth + 1);
order(root->right,v,depth + 1);
}
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>v;
int depth = 0;
order(root,v,depth);
return v;
}
};
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:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*>q;
vector<vector<int>>res;
TreeNode* node;
if(root == nullptr)return res;
q.push(root);
while(!q.empty()){
int OneLevelNum = q.size();
vector<int>v;
for(int i = 0;i < OneLevelNum;i++){
node = q.front();
q.pop();
v.push_back(node->val);
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
res.push_back(v);
}
return res;
}
};
107. 二叉树的层序遍历 II
给你二叉树的根节点 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:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>>res;
TreeNode*node;
queue<TreeNode*>q;
if(root != nullptr)q.push(root);
while(!q.empty()){
vector<int>v;
int oneLeveSize = q.size();
for(int i = 0;i < oneLeveSize;i++){
node = q.front();
q.pop();
v.push_back(node->val);
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
res.push_back(v);
}
reverse(res.begin(),res.end());
return res;
}
};
199. 二叉树的右视图
给定一个二叉树的 根节点 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:
vector<int> rightSideView(TreeNode* root) {
vector<int>res;
TreeNode*node;
queue<TreeNode*>q;
if(root != nullptr)q.push(root);
while(!q.empty()){
vector<int>v;
int oneLeveSize = q.size();
for(int i = 0;i < oneLeveSize;i++){
node = q.front();
q.pop();
v.push_back(node->val);
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
res.push_back(v.back());
}
return res;
}
};
637. 二叉树的层平均值
给定一个非空二叉树的根节点 root
, 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5
以内的答案可以被接受。
/**
* 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:
vector<double> averageOfLevels(TreeNode* root) {
queue<TreeNode*>q;
TreeNode* node;
vector<double>v;
if(root != nullptr)q.push(root);
while(q.size()){
double sum = 0;
int leverSize = q.size();
for(int i = 0;i < leverSize;i++){
node = q.front();
q.pop();
sum += node->val;
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
double average = sum / leverSize;
v.push_back(average);
}
return v;
}
};
429. N 叉树的层序遍历
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> order;
Node* node;
queue<Node*>q;
if(root != NULL)q.push(root);
while(q.size()){
vector<int>v;
int levelSize = q.size();
for(int i = 0;i < levelSize;i++){
node = q.front();
q.pop();
v.push_back(node->val);
if(node->children.size() != 0){
for(int j = 0;j < node->children.size();j++){
q.push(node->children[j]);
}
}
}
order.push_back(v);
}
return order;
}
};
515. 在每个树行中找最大值
给定一棵二叉树的根节点 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:
vector<int> largestValues(TreeNode* root) {
queue<TreeNode*>q;
TreeNode* node;
vector<int>v;
if(root != nullptr) q.push(root);
while(q.size()){
int leverSize = q.size();
int max = q.front()->val;
for(int i = 0;i < leverSize;i++){
node = q.front();
q.pop();
if(max < node->val){
max = node->val;
}
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
v.push_back(max);
}
return v;
}
};
116. 填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL
。
初始状态下,所有 next 指针都被设置为 NULL
。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
Node* node;
queue<Node*>q;
if(root != NULL)q.push(root);
while(q.size()){
int leverSize = q.size();
for(int i = 0;i < leverSize;i++){
node = q.front();
q.pop();
if(i < leverSize - 1){
node->next = q.front();
}
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
}
return root;
}
};
117. 填充每个节点的下一个右侧节点指针 II
给定一个二叉树
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL
。
初始状态下,所有 next 指针都被设置为 NULL
。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
Node* node;
queue<Node*>q;
if(root != NULL)q.push(root);
while(q.size()){
int leverSize = q.size();
for(int i = 0;i < leverSize;i++){
node = q.front();
q.pop();
if(i < leverSize - 1){
node->next = q.front();
}
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
}
return root;
}
};
5.翻转二叉树
226.翻转二叉树
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
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:
//递归法
void inver(TreeNode* node){
if(node == nullptr)return ;
swap(node->left,node->right);
inver(node->left);
inver(node->right);
}
TreeNode* invertTree(TreeNode* root) {
inver(root);
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:
TreeNode* invertTree(TreeNode* root) {
TreeNode* node;
stack<TreeNode*>st;
if(root != nullptr)st.push(root);
while(st.size()){
node = st.top();
st.pop();
swap(node->left,node->right);
if(node->left)st.push(node->left);
if(node->right)st.push(node->right);
}
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* invertTree(TreeNode* root) {
queue<TreeNode*>q;
TreeNode* node;
if(root != nullptr)q.push(root);
while(q.size()){
int size = q.size();
for(int i = 0;i < size;i++){
node = q.front();
q.pop();
swap(node->left,node->right);
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
}
return root;
}
};
6.对称二叉树
101. 对称二叉树
给你一个二叉树的根节点 root
, 检查它是否轴对称。
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:
bool isNot(TreeNode* left,TreeNode* right){
if (left == NULL && right == NULL) return true;
else if(left == NULL || right == NULL) return false;
if(left->val != right->val)return false;
bool one = isNot(left->left,right->right);
bool two = isNot(left->right,right->left);
return one && two;
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr)return true;
return isNot(root->left,root->right);
}
};
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:
bool isSymmetric(TreeNode* root) {
if(root == nullptr)return true;
queue<TreeNode*>q;
TreeNode* left;
TreeNode* right;
q.push(root->left);
q.push(root->right);
while(q.size()){
right = q.front();
q.pop();
left = q.front();
q.pop();
if(left == nullptr && right == nullptr) continue;
if(!left || !right || left->val != right->val)return false;
q.push(left->left);
q.push(right->right);
q.push(left->right);
q.push(right->left);
}
return true;
}
};
栈
/**
* 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:
bool isSymmetric(TreeNode* root) {
if(root == nullptr)return true;
stack<TreeNode*>st;
TreeNode* left;
TreeNode* right;
st.push(root->left);
st.push(root->right);
while(st.size()){
right = st.top();
st.pop();
left = st.top();
st.pop();
if(left == nullptr && right == nullptr) continue;
if(!left || !right || left->val != right->val)return false;
st.push(left->left);
st.push(right->right);
st.push(left->right);
st.push(right->left);
}
return true;
}
};
100. 相同的树
给你两棵二叉树的根节点 p
和 q
,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
/**
* 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:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p == nullptr && q == nullptr)return true;
queue<TreeNode*>q1;
queue<TreeNode*>q2;
if(p != nullptr && q != nullptr && q->val == p->val){
q1.push(p);
q2.push(q);
}
else return false;
while(q1.size() && q2.size()){
TreeNode* left = q1.front();
q1.pop();
TreeNode* right =q2.front();
q2.pop();
if(left == nullptr && right == nullptr)continue;
if(!left || !right || left->val != right->val)return false;
q1.push(left->left);
q1.push(left->right);
q2.push(right->left);
q2.push(right->right);
}
return true;
}
};
572.另一个树的子树
给你两棵二叉树 root
和 subRoot
。检验 root
中是否包含和 subRoot
具有相同结构和节点值的子树。如果存在,返回 true
;否则,返回 false
。
二叉树 tree
的一棵子树包括 tree
的某个节点和这个节点的所有后代节点。tree
也可以看做它自身的一棵子树。
/**
* 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:
bool isSame(TreeNode* root,TreeNode * subRoot){
queue<TreeNode*>left;
queue<TreeNode*>right;
if(root != nullptr && subRoot != nullptr && root->val == subRoot->val){
left.push(root);
right.push(subRoot);
}
else return false;
while(left.size() && right.size()){
TreeNode* curLeft = left.front();
TreeNode* curright = right.front();
left.pop();
right.pop();
if(curLeft == nullptr && curright == nullptr)continue;
if(!curLeft || !curright || curLeft->val != curright->val)return false;
left.push(curLeft->left);
left.push(curLeft->right);
right.push(curright->left);
right.push(curright->right);
}
return true;
}
bool isSubtree(TreeNode* root, TreeNode* subRoot) {
if(root == nullptr && subRoot == nullptr)return true;
if(root == nullptr && subRoot != nullptr)return false;
if(root != nullptr && subRoot == nullptr)return true;
queue<TreeNode*>q;
q.push(root);
while(q.size()){
TreeNode* cur = q.front();
q.pop();
bool is = isSame(cur,subRoot);
if(is == true)return true;
if(cur->left)q.push(cur->left);
if(cur->right)q.push(cur->right);
}
return false;
}
};
7.二叉树的最大深度
104. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
/**
* 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 maxDepth(TreeNode* root) {
queue<TreeNode*>q;
if(root == nullptr)return 0;
q.push(root);
int sum = 0;
while(q.size()){
int oneSize = q.size();
for(int i = 0;i < oneSize;i++){
TreeNode* node = q.front();
q.pop();
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
sum++;
}
return sum;
}
};
8.二叉树的最小深度
111.二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
/**
* 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 minDepth(TreeNode* root) {
queue<TreeNode*>q;
if(root == nullptr)return 0;
q.push(root);
int sum = 0;
TreeNode* node;
while(q.size()){
int oneSize = q.size();
for(int i = 0;i < oneSize;i++){
node = q.front();
q.pop();
if(node->left ==nullptr && node->right == nullptr)break;
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
sum++;
if(node->left ==nullptr && node->right == nullptr)break;
}
return sum;
}
};
9.完全二叉树节点个数
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2h
个节点。
222.完全二叉树节点个数
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
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:
int countNodes(TreeNode* root) {
queue<TreeNode*>q;
TreeNode* node;
int count = 0;
if(root == nullptr)return count;
q.push(root);
while(!q.empty()){
int OneLevelNum = q.size();
for(int i = 0;i < OneLevelNum;i++){
node = q.front();
q.pop();
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
count += OneLevelNum;
}
return count;
}
};
2.利用完全二叉树性质
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况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:
int countNodes(TreeNode* root) {
int left = 0,right = 0;
if(root == nullptr)return 0;
TreeNode* leftNode = root->left;
TreeNode* rightNode = root->right;
while(leftNode){
leftNode = leftNode->left;
left++;
}
while(rightNode){
rightNode = rightNode->right;
right++;
}
if(left == right){
return (2 << left) - 1;
}
return countNodes(root->left) + countNodes(root->right) + 1;//不要返回局部变量
}
};
*10.平衡二叉树
深度与高度区别:
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)
/**
* 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 height(TreeNode* node){
if(node == nullptr)return 0;
int left = height(node->left);
if(left == -1)return -1;
int right = height(node->right);
if(right == -1)return -1;
int maxHeight = 0;
if(abs(left - right) > 1){
return -1;
}
else{
maxHeight = 1 + max(left,right);
return maxHeight;
}
return maxHeight;
}
bool isBalanced(TreeNode* root) {
if(height(root) == -1)return false;
else return true;
}
};
11.二叉树的所有路径
257. 二叉树的所有路径
给你一个二叉树的根节点 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:
void treePaths(TreeNode* node,vector<int> &v,vector<string>&vs){
string s;
v.push_back(node->val);
if(node->left == nullptr && node->right == nullptr){
for(int i = 0; i < v.size() - 1;i++){
s = s + to_string(v[i]);//将int转换为string
s += "->";
}
s = s + to_string(v[v.size() - 1]);
vs.push_back(s);
return;
}
if(node->left){
treePaths(node->left,v,vs);
v.pop_back();//这条路访问完了,最后一个子节点删除
}
if(node->right){
treePaths(node->right,v,vs);
v.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<int>v;
vector<string>vs;
treePaths(root,v,vs);
return vs;
}
};
12.左叶子之和
404.左叶子之和
计算给定二叉树的所有左叶子之和。
/**
* 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 sumOfLeftLeaves(TreeNode* root) {
int sum = 0;
stack<TreeNode*>st;
if(root != nullptr)st.push(root);
while(st.size()){
TreeNode* node = st.top();
if(node != nullptr){
st.pop();
if(node->right)st.push(node->right);
st.push(node);
st.push(nullptr);
if(node->left){
st.push(node->left);
if(node->left->left == nullptr && node->left->right == nullptr){
sum += node->left->val;
}
}
}
else{
st.pop();
st.pop();
}
}
return sum;
}
};
13.找树左下角的值
513.找树左下角的值
给定一个二叉树,在树的最后一行找到最左边的值。
/**
* 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 findBottomLeftValue(TreeNode* root) {
int leftValue = 0;
queue<TreeNode*>q;
if(root != nullptr)q.push(root);
while(q.size()){
int size = q.size();
leftValue = q.front()->val;
for(int i = 0;i < size; i++){
TreeNode* node = q.front();
q.pop();
if(node->left)q.push(node->left);
if(node->right)q.push(node->right);
}
}
return leftValue;
}
};
14.路径总和
112. 路径总和
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
/**
* 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:
bool isSum(TreeNode* node,int targetSum,vector<int>&v){
if(node == nullptr)return false;
v.push_back(node->val);
int sum = 0;
if(node->left == nullptr && node->right == nullptr){
for(int i = 0;i < v.size();i++){
sum += v[i];
}
if(sum == targetSum)return true;
}
if(node->left){
bool isNot = isSum(node->left,targetSum,v);
if(isNot == true)return true;
v.pop_back();
}
if(node->right){
bool isNot = isSum(node->right,targetSum,v);
if(isNot == true)return true;
v.pop_back();
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
vector<int>v;
return isSum(root,targetSum,v);
}
};
113. 路径总和 II
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
/**
* 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:
void path(TreeNode* node,int targetSum,vector<int>&v,vector<vector<int>>&vv){
v.push_back(node->val);
int sum = 0;
if(node->left == nullptr && node->right == nullptr){
for(int i = 0;i < v.size();i++){
sum += v[i];
}
if(sum == targetSum){
vv.push_back(v);
}
}
if(node->left){
path(node->left,targetSum,v,vv);
v.pop_back();
}
if(node->right){
path(node->right,targetSum,v,vv);
v.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>>vv;
vector<int>v;
if(root == nullptr)return vv;
path(root,targetSum,v,vv);
return vv;
}
};
*15.从中序,后序遍历序列来构造二叉树
106. 从中序与后序遍历序列构造二叉树
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
/**
* 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>& inorder, vector<int>& postorder){
//根据后序排序来分割中序排序,通过中序排序左右边大小来分割后序排序左右边
//靠后续排序值来确定二叉树
if(postorder.size() == 0)return nullptr;
TreeNode* root = new TreeNode(postorder[postorder.size() - 1]);
int index = 0;//每次分割中间值所在中序排序的位置
for(;index < inorder.size();index++){
if(inorder[index] == root->val)break;
}
//中序分割
//重定义数组为[ , );左闭右开
vector<int>leftInorder(inorder.begin(),inorder.begin() + index);
vector<int>rightInorder(inorder.begin() + index + 1,inorder.end());//中间index那位为中间点去掉
vector<int>leftPostorder(postorder.begin(), postorder.begin() + index);
vector<int>rightPostorder(postorder.begin() + index,postorder.end() - 1);//最后一位是中间点去掉
root->right = traversal(rightInorder,rightPostorder);
root->left = traversal(leftInorder,leftPostorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size() == 0 || inorder.size() == 0)return nullptr;
return traversal(inorder,postorder);
}
};
105. 从前序与中序遍历序列构造二叉树
/**
* 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* travel(vector<int>& preorder,vector<int>& inorder){
if(preorder.size() == 0)return nullptr;
TreeNode* root = new TreeNode(preorder[0]);
int index = 0;
for(;index < inorder.size();index++){
if(inorder[index] == preorder[0]){
break;
}
}
vector<int>leftInorder(inorder.begin(),inorder.begin() + index);
vector<int>rightInorder(inorder.begin() + index + 1,inorder.end());
vector<int>leftPreorder(preorder.begin() + 1,preorder.begin() + index + 1);
vector<int>rightPreorder(preorder.begin() + index + 1, preorder.end());
root->left = travel(leftPreorder,leftInorder);
root->right = travel(rightPreorder,rightInorder);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size() == 0 || inorder.size() == 0){
return nullptr;
}
return travel(preorder,inorder);
}
};
16.最大二叉树
654. 最大二叉树
给定一个不重复的整数数组 nums
。 最大二叉树 可以用下面的算法从 nums
递归地构建:
- 创建一个根节点,其值为
nums
中的最大值。 - 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums
构建的 最大二叉树 。
/**
* 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* maxTree(vector<int>& nums){
//终止条件
if(nums.size() == 0)return nullptr;
//找最大值
int max = 0;
for(int index = 0;index < nums.size();index++){
if(nums[index] > nums[max])max = index;
}
TreeNode* root = new TreeNode(nums[max]);
vector<int>right(nums.begin() + max + 1,nums.end());
vector<int>left(nums.begin(),nums.begin() + max);
root->right = maxTree(right);
root->left = maxTree(left);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.size() == 0)return nullptr;
return maxTree(nums);
}
};
17.合并二叉树
617.合并二叉树
给你两棵二叉树: root1
和 root2
。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
/**
* 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* merge(TreeNode* root1,TreeNode* root2){
if(root2 == nullptr)return root1;
if(root1 != nullptr)root1->val += root2->val;
else if(root1 == nullptr) return root2;
root1->left = merge(root1->left,root2->left);
root1->right = merge(root1->right,root2->right);
return root1;
}
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1 == nullptr && root2 == nullptr)return nullptr;
if(root1 != nullptr && root2 == nullptr)return root1;
if(root1 == nullptr && root2 != nullptr)return root2;
return merge(root1,root2);
}
};
18.二叉搜索树中的搜索
700.二叉搜索树中的搜索
给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。
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:
void bst(TreeNode* root, int val, TreeNode* &search){
if(root == nullptr)return ;
if(root->val == val)search = root;
bst(root->left,val,search);
bst(root->right,val,search);
}
TreeNode* searchBST(TreeNode* root, int val) {
if(root == nullptr)return nullptr;
TreeNode* search = nullptr;
bst(root,val,search);
return search;
}
};
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:
void bst(TreeNode* root, int val, TreeNode* &search){
if(root == nullptr)return ;
if(root->val == val)search = root;
if(root->val > val) bst(root->left,val,search);
if(root->val < val) bst(root->right,val,search);
}
TreeNode* searchBST(TreeNode* root, int val) {
if(root == nullptr)return nullptr;
TreeNode* search = nullptr;
bst(root,val,search);
return search;
}
};
20.验证二叉搜索树
98.验证二叉搜索树
给你一个二叉树的根节点 root
,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
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:
void travel(TreeNode* root,vector<int>&v){
if(root == nullptr)return;
travel(root->left,v);
v.push_back(root->val);
travel(root->right,v);
return;
}
bool isValidBST(TreeNode* root) {
vector<int>v;
travel(root,v);
for(int i = 0;i < v.size() - 1;i++){
if(v[i] >= v[i + 1])return false;
}
return true;
}
};
21.二叉搜索树的最小绝对差
530.二叉搜索树的最小绝对差
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
/**
* 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:
void travel(TreeNode* root,vector<int>&v){
if(root == nullptr)return;
travel(root->left,v);
v.push_back(root->val);
travel(root->right,v);
return;
}
int getMinimumDifference(TreeNode* root) {
vector<int>v;
travel(root,v);
int min = v[1] - v[0];
for(int i = 1;i < v.size() - 1;i++){
if((v[i + 1] - v[i]) < min)min = v[i + 1] - v[i];
if(min == 1)return min;
}
return min;
}
};
22. 二叉搜索树中的众数
501. 二叉搜索树中的众数
给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
/**
* 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:
void travel(TreeNode* node,map<int,int>&m){
if(node == nullptr)return ;
travel(node->right,m);
m[node->val]++;
travel(node->left,m);
return;
}
vector<int> findMode(TreeNode* root) {
map<int,int>m;
vector<int>v;
travel(root,m);
auto it = m.begin();
auto it1 = m.begin();
v.push_back(it->first);
it++;
for(;it != m.end();it++){
if(it->second > it1->second){
v.clear();
v.push_back(it->first);
it1 = it;
}
else if(it->second == it1->second){
v.push_back(it->first);
}
}
return v;
}
};
**23. 二叉搜索树的最近公共祖先
235. 二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
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;
else if(left != NULL && right == NULL)return left;
else if(left == NULL && right != NULL)return right;
else return NULL;
}
};
24.二叉搜索树中的插入操作
701.二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。
/**
* 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* insert(TreeNode* root,int val){
if(val > root->val && root->right != nullptr){
insert(root->right,val);
}
else if(val > root->val && root->right == nullptr){
TreeNode* node = new TreeNode(val);
root->right = node;
return root;
}
else if(val < root->val && root->left != nullptr){
insert(root->left,val);
}
else if(val < root->val && root->left == nullptr){
TreeNode* node = new TreeNode(val);
root->left = node;
return root;
}
return root;
}
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root == nullptr){
TreeNode* node = new TreeNode(val);
return node;
}
return insert(root,val);
}
};
25.删除二叉搜索树中的节点
450.删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点; 如果找到了,删除它。 说明: 要求算法时间复杂度为 O ( h ) O(h) O(h),h 为树的高度。
/**
* 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* deleted(TreeNode*root,int key){
if(root == nullptr)return root;
if(root->val == key){
if(root->left == nullptr && root->right == nullptr){
delete root;
return nullptr;
}
else if(root->left != nullptr && root->right == nullptr){
TreeNode* node = root->left;
delete root;
return node;
}
else if(root->left == nullptr && root->right != nullptr){
TreeNode* node = root->right;
delete root;
return node;
}
else{
TreeNode* node = root->right;
while(node->left){
node = node->left;
}
node->left = root->left;
TreeNode* nodell = root;
root = root->right;
delete nodell;
return root;
}
}
else if(key > root->val){
root->right = deleted(root->right,key);
}
else if(key < root->val){
root->left = deleted(root->left,key);
}
return root;
}
TreeNode* deleteNode(TreeNode* root, int key) {
if(root == nullptr ){
return nullptr;
}
return deleted(root,key);
}
};
26. 修剪二叉搜索树
669. 修剪二叉搜索树
给你二叉搜索树的根节点 root
,同时给定最小边界low
和最大边界 high
。通过修剪二叉搜索树,使得所有节点的值在[low, 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* cut(TreeNode* root,int high,int low){
if(root == nullptr)return root;
if(root->val < low){
return cut(root->right,high,low);
}
else if(root->val > high){
return cut(root->left,high,low);
}
root->left = cut(root->left,high,low);
root->right = cut(root->right,high,low);
return root;
}
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root == nullptr)return nullptr;
return cut(root,high,low);
}
};
27.将有序数组转换为二叉搜索树
108.将有序数组转换为二叉搜索树
给你一个整数数组 nums
,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 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* travel(vector<int>&nums,int left,int right){
if(left > right)return nullptr;
int mid = (right + left)/2;
TreeNode* node = new TreeNode(nums[mid]);
node->right = travel(nums,mid+1,right);
node->left = travel(nums,left,mid - 1);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
int left = 0;
int right = nums.size() - 1;
return travel(nums,left,right);
}
};
*28.把二叉搜索树转换为累加树
538.把二叉搜索树转换为累加树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node
的新值等于原树中大于或等于 node.val
的值之和。
提醒一下,二叉搜索树满足下列约束条件:
- 节点的左子树仅包含键 小于 节点键的节点。
- 节点的右子树仅包含键 大于 节点键的节点。
- 左右子树也必须是二叉搜索树。
/**
* 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:
void travel(TreeNode* root,int &num){
if(root == nullptr)return ;
if(root->right)travel(root->right,num);
root->val += num;
num = root->val;
if(root->left)travel(root->left,num);
return;
}
TreeNode* convertBST(TreeNode* root) {
int num = 0;
if(root == nullptr)return nullptr;
travel(root,num);
return root;
}
};