2022/7/30
144. 二叉树的前序遍历
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 1:

输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:

输入:root = [1,2]
输出:[1,2]
示例 5:

输入:root = [1,null,2]
输出:[1,2]
解题思路:
方法一:递归法
前序遍历二叉树的遍历节点的顺序为:根左右,即先遍历根节点,再遍历左节点,右节点。
解题过程
1.确定递归函数的参数和返回值
参数的确定:首先,每次递归过程中要放一个节点进行处理,即参数1设为一个节点。其次要放入一个数组用于保存节点的val值。
void preorder(TreeNode *root,vector<int>& nums)
2.确定终止条件:
终止条件是遍历完所有的叶子结点,即当前节点为空,也就是叶子结点的left和叶子节点的right都为空,当节点为空时,我们直接return;也就是结束当前程序,递归不在继续进行。当所有叶子节点的程序结束时,这个递归程序也就结束了
if (root == nullptr) return;
3.确定单层递归的逻辑:
首先,我们将当前节点,也就是传进来的root节点的val值,放入到数组nums当中,然后依次遍历该节点的左节点、右节点。
nums.push_back(root->val);
preorder(root->left,nums);
preorder(root->right,nums);
时间复杂度:O(n),二叉树的每个元素都被访问了1次。
空间复杂度:O(n),栈中的开销。
代码:
/**
* 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 preorder(TreeNode *root,vector<int>& nums){
if(root==nullptr) return;
nums.push_back(root->val);
preorder(root->left,nums);
preorder(root->right,nums);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> nums;
preorder(root,nums);
return nums;
}
};
c:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void preorder(struct TreeNode* root,int* res,int* returnSize){
if(root==NULL)
return;
res[*returnSize]=root->val;
(*returnSize)++;
preorder(root->left,res,returnSize);
preorder(root->right,res,returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int* nums=malloc(sizeof(int)*2000);
*returnSize=0;
preorder(root,nums,returnSize);
return nums;
}
方法二:非递归法也就是迭代法
前序遍历的顺序为根左右,首先,我们现将根结点放入栈中,然后弹出放入到一个一维数组results当中,一维数组用于存放访问节点的值。
然后将此节点的右节点、左节点依次放入栈中,这样弹出节点时的顺序是先将左节点弹出放入到数组results,后将右节点弹出放入到数组results中。实现了数组中存放顺序为根左右。
我们判断当二叉树中的所有元素都被放入到栈后、且被栈弹出后,即栈为空时,结束while循环,返回数组results。
时间复杂度:O(n),二叉树的每个元素都被访问了1次。
空间复杂度:O(n),栈中的开销。
实现代码:
/**
* 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;
vector<int> result;
if(root==nullptr)
return result;
st.push(root);
while(st.empty()==false)
{
TreeNode* node=st.top();
st.pop();
result.push_back(node->val);
if(node->right!=nullptr)
st.push(node->right);
if(node->left!=nullptr)
st.push(node->left);
}
return result;
}
};
c:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int *res=malloc(sizeof(int)*2000);
* returnSize=0;
int sum=0;
if(root==NULL)
return res;
struct TreeNode* stk[2000];
int top=0;
stk[top]=root;
top++;
while(top>0)
{
struct TreeNode * node=stk[top-1];
res[(*returnSize)++]=node->val;
top--;
if(node->right!=NULL)
stk[top++]=node->right;
if(node->left!=NULL)
stk[top++]=node->left;
}
return res;
}
栈的相关概念:
栈的empty()函数:用于返回堆栈是否为空,当返回值为true时,堆栈为空。当返回值为false时,堆栈不为空。
返回类型:布尔型(True或False)正确:堆栈为空
False:堆栈不为空
2022/7/31
144. 94. 二叉树的中序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [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:
void inorder(TreeNode* root,vector<int> &nums){
if(root==nullptr)
return;
inorder(root->left,nums);
nums.push_back(root->val);
inorder(root->right,nums);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> nums;
inorder(root,nums);
return nums;
}
};
c:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void inorder(struct TreeNode* root,int * res,int* returnSize){
if(root==NULL)
return;
inorder(root->left,res,returnSize);
res[(*returnSize)++]=root->val;
inorder(root->right,res,returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int *res=malloc(sizeof(int)*2000);
*returnSize=0;
inorder(root,res,returnSize);
return res;
}
非递归遍历分为:
1.进栈:
创建一个指针ptr,指向根节点,先从根节点开始遍历,然后在一层一层的向下访问,每次都访问节点的左孩子节点,即ptr=ptr->left直到访问到树左面的最底部,在这个过程中每访问一个节点,就把该节点进栈。
2.出栈
当访问到树左面的最底部的节点时,其左孩子节点为空,即left为空时,让ptr指针指向栈顶的节点,将栈顶节点的值添加到nums数组中,将该节点出栈,让ptr=ptr->right;
代码:
/**
* 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) {
vector<int> nums;
if(root==nullptr)
return nums;
stack<TreeNode*> st;
TreeNode *ptr=root;
while(st.empty()==false||ptr!=nullptr){
if(ptr!=nullptr){ st.push(ptr);
ptr=ptr->left;}
else
{
ptr=st.top();
st.pop();
nums.push_back(ptr->val);
ptr=ptr->right;
}
}
return nums;
}
};
2022/8/1 monday
145. 二叉树的后序遍历
1.递归法解题思路:
使用递归方法,首先遍历左节点、右节点、根节点。
递归结束的条件为:当结点为空时,递归结束。
时间复杂度:O(n)
空间复杂度:O(n)
代码:
/**
* 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 afterorder(TreeNode* root,vector<int>&nums){
if(root==nullptr) return;
afterorder(root->left,nums);
afterorder(root->right,nums);
nums.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> nums;
afterorder(root,nums);
return nums;
}
};
2.非递归法解题思路:
再来看后序遍历,先序遍历是根左右,后续遍历是左右根,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右根了。
代码:
/**
* 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;
vector<int> nums;
st.push(root);
if(root==nullptr)
return nums;
while(st.empty()==false)
{
TreeNode* node=st.top();
st.pop();
nums.push_back(node->val);
if(node->left!=nullptr)
st.push(node->left);
if(node->right!=nullptr)
st.push(node->right);
}
reverse(nums.begin(),nums.end());
return nums;
}
};
102. 二叉树的层序遍历
解题思路:
使用队列来模拟层序遍历,一层一层的进行遍历。
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
在思路上更像广度优先搜索遍历。
时间复杂度:每个点进队出队各一次,O(n)
空间复杂度:队列中元素的个数不超过n个,O(n)
代码:
/**
* 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*> que;
if(root!=nullptr)
que.push(root);
vector<vector<int>> result;
while(que.empty()==false)
{
int size=que.size();
vector<int> vec;
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
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 result;
}
};
2022/8/2
104. 二叉树的最大深度
解题思路:
我们可以用「广度优先搜索」的方法来解决这道题目,但我们需要对其进行一些修改,此时我们广度优先搜索的队列里存放的是「当前层的所有节点」。每次拓展下一层的时候,不同于广度优先搜索的每次只从队列里拿出一个节点,我们需要将队列里的所有节点都拿出来进行拓展,这样能保证每次拓展完的时候队列里存放的是当前层的所有节点,即我们是一层一层地进行拓展,层数加1.
时间复杂度:n为二叉树的节点,每个节点只会被访问一次。O(n)
空间复杂度:队列中元素的个数不超过n个,O(n)
代码:
/**
* 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) {
if(root==nullptr)
return 0;
queue <TreeNode*> que;
que.push(root);
int n=0;
while(que.empty()==false){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode *node=que.front();
que.pop();
if(node->left!=nullptr)
que.push(node->left);
if(node->right!=nullptr)
que.push(node->right);
}
n++;
}
return n;
}
};
200. 岛屿数量
解题思路为:
首先我们先找到值为1的点,将这点赋值为0,然后判断这个点的相邻的3个点是否为1,也就是若为1,将这3个点的赋值为0,然后再分别将这三个点的相邻的三个点判断,判断是否为1,若为1则将其值赋值为0.一直递归下去,直到遍历完整个二维数组。
时间复杂度:O(mn),m为行,n为列
空间复杂度:最坏情况下都为陆地则O(mn)。
代码:
class Solution {
public:
void dfs(vector<vector<char>>& grid,int row,int column){
int nrow=grid.size();
int ncolumn=grid[0].size();
grid[row][column]='0';
if(row-1>=0&&grid[row-1][column]=='1') dfs(grid,row-1,column);
if(row+1<=nrow-1&&grid[row+1][column]=='1')
dfs(grid,row+1,column);
if(column-1>=0&&grid[row][column-1]=='1')
dfs(grid,row,column-1);
if(column+1<=ncolumn-1&&grid[row][column+1]=='1')
dfs(grid,row,column+1);
}
int numIslands(vector<vector<char>>& grid) {
int nr=grid.size();
if(nr==0)
return 0;
int nc=grid[0].size();
int num_island=0;
for(int i=0;i<nr;i++)
for(int j=0;j<nc;j++)
{
if(grid[i][j]=='1')
{
num_island++;
dfs(grid,i,j);
}
}
return num_island;
}
};
2022/8/4
112. 路径总和
解题思路为:
1.确定递归函数的参数和返回类型
参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。
先遍历完一个节点的左子树,再遍历其右子树。
2.确定终止条件
首先计数器如何统计这一条路径的和呢?
不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。
如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。
如果遍历到了叶子节点,count不为0,就是没找到。
3.确定单层递归的逻辑
因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。
递归函数是有返回值的,如果递归函数返回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 traversal(TreeNode*cur,int count){
if(cur->left==nullptr&&cur->right==nullptr&&count==0)
return true;
if(cur->left==nullptr&&cur->right==nullptr&&count!=0)
return false;
if(cur->left!=nullptr)
{
count-=cur->left->val;
if(traversal(cur->left,count))
return true;
count+=cur->left->val;
}
if(cur->right!=nullptr)
{
count-=cur->right->val;
if(traversal(cur->right,count))
return true;
count+=cur->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr)
return false;
return traversal(root,targetSum-root->val);
}
};
2022/8/7
106. 从中序与后序遍历序列构造二叉树
解题思路:
给了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* traversal(vector<int> &inorder,vector<int>& postorder){
if(postorder.size()==0)
return nullptr;
//后序遍历数组的最后一个元素,就是当前的根节点
int rootValue=postorder[postorder.size()-1];
TreeNode* root=new TreeNode(rootValue);
if(postorder.size()==1)
return root;
//找到中序遍历的分割点
int division;
for(division=0;division<inorder.size();division++){
if(inorder[division]==rootValue)
break;
}
//切割数组
//左闭右开区间
vector<int> leftInorder(inorder.begin(),inorder.begin()+division);
vector<int> rightInorder(inorder.begin()+division+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);
}
};
105. 从前序与中序遍历序列构造二叉树
c++代码:
/**
* 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* Travesal(vector<int>& preorder,vector<int>& inorder){
if(inorder.size()==0)
return nullptr;
int x=preorder[0];
TreeNode* node= new TreeNode(x);
if(preorder.size()==1)
return node;
int division;
for(division=0;division<inorder.size();division++)
{
if(inorder[division]==x)
break;
}
vector<int> leftInorder(inorder.begin(),inorder.begin()+division);
vector<int> rightInorder(inorder.begin()+division+1,inorder.end());
preorder.erase(preorder.begin());
vector<int> leftpreorder(preorder.begin(),preorder.begin()+division);
vector<int> rightpreorder(preorder.begin()+division,preorder.end());
node->left=Travesal(leftpreorder,leftInorder);
node->right=Travesal(rightpreorder,rightInorder);
return node;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0||inorder.size()==0)
return nullptr;
return Travesal(preorder,inorder);
}
};
vector数组中的erase方法:
erase(position);表示删除postion处的一个字符或数字
vector<int> preorder(10);
preorder.erase(preorder.begin());表示删除数组的首元素。
2022/8/9
116. 填充每个节点的下一个右侧节点指针
使用层序遍历,在每一层遍历的过程中,将一层的元素连接起来。
时间复杂度:O(N)。每个节点会被访问一次且只会被访问一次,即从队列中弹出,并建立next 指针。
空间复杂度:O(N)。这是一棵完美二叉树,它的最后一个层级包含 N/2 个节点。广度优先遍历的复杂度取决于一个层级上的最大元素数量。这种情况下空间复杂度为 O(N)。
代码:
/*
// 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) {
queue<Node*> que;
if(root==nullptr)
return 0;
que.push(root);
while(que.empty()==false)
{
int size=que.size();
for(int i=0;i<size;i++)
{
Node * tNode=que.front();
que.pop();
if(i<size-1){
tNode->next=que.front();
}
if(tNode->left!=nullptr)
que.push(tNode->left);
if(tNode->right!=nullptr)
que.push(tNode->right);
}
}
return root;
}
};
2022/8/9---->2022/8/14
就一个题,最近公共祖先,也没弄会。这个真难,我就不会了,就这一个题把我劝退了,尴尬了好几天,我是真的服了、我也自闭了好几天,心酸了好几天,自我怀疑了好几天,认为自己不行,否定自己,没有生活的希望了,没有继续学习的希望了,难过死了,不过最后到14号也没有解决,我只能先放下这个题,不再继续精神内耗了,老子不耗了,做二叉搜索树的题,跑路了,继续加油,为了支持和陪伴我的人,我也得坚持下去,
2022/8/14
98. 验证二叉搜索树
二叉搜索树的中序遍历是递增序列,所以只需判断它是否是递增即可解决这道题。
时间复杂度:O(n)
空间复杂度:O(n)
/**
* 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> vec;
void inorder(TreeNode* root){
if(root==nullptr)
return ;
inorder(root->left);
vec.push_back(root->val);
inorder(root->right);
}
bool isValidBST(TreeNode* root) {
vec.clear();
inorder(root);
for(int i=1;i<vec.size();i++)
{
if(vec[i]<=vec[i-1])
return false;
}
return true;
}
};
2022/8/15
700. 二叉搜索树中的搜索
解题思路:其实是就是遍历这个树,然后找到符合条件的树的节点,返回这个节点,因为是二叉搜索树,所以遍历比较特殊,当val大于节点时,往此节点的右子树寻找。当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:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==nullptr)
return root;
if(root->val==val)
return root;
if(val>root->val)
return searchBST(root->right,val);
if(val<root->val)
return searchBST(root->left,val);
return nullptr;
}
};
2022/8/16
701. 二叉搜索树中的插入操作
插入操作是在叶子结点处进行插入的,当对节点进行遍历的过程中,当val值>root->val时,向右子树方向遍历,当val值<root->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:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root==nullptr)
{
TreeNode *node=new TreeNode(val);
return node;
}
else
{
if(val<root->val)
root->left=insertIntoBST(root->left,val);
else
root->right=insertIntoBST(root->right,val);
}
return root;
}
};
2022/8/17
450. 删除二叉搜索树中的节点
确定递归函数参数以及返回值
说道递归函数的返回值,在二叉树:搜索树中的插入操作中通过递归返回值来加入新节点, 这里也可以通过递归返回值删除节点。
代码如下:
TreeNode* deleteNode(TreeNode* root, int key)
确定终止条件
遇到空返回,其实这也说明没找到删除的节点,遍历到空节点直接返回了
if (root == nullptr) return root;
确定单层递归的逻辑
这里就把平衡二叉树中删除节点遇到的情况都搞清楚。
有以下五种情况:
第一种情况:没找到删除的节点,遍历到空节点直接返回了
找到删除的节点
第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
代码:
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;
}
};
BM35 判断是不是完全二叉树
这个题是牛客网上的题。
解题思路为:
完全二叉树的定义:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。

算法思想:采用层次遍历的算法,将所有节点加入到队列中(包括空节点),当节点为非空节点,查看其前是否有空节点,若有,则该二叉树不是完全二叉树。
代码:
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return bool布尔型
*/
bool isCompleteTree(TreeNode* root) {
// write code here
queue<TreeNode*> que;
if(root==nullptr)
return true;
que.push(root);
bool flag=false;
while(que.empty()==false)
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
que.pop();
if(node==nullptr)
flag=true;
else
{
if(flag==true) //当非空节点的前面有空节点时,该二叉树不是完全二叉树
return false;
que.push(node->left);
que.push(node->right);
}
}
}
return true;
}
};
226. 翻转二叉树
可以使用前序和后序遍历进行交换,但不能使用中序遍历。将根节点的左子树和右子树进行交换。
后序遍历递归法:
/**
* 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 swap(TreeNode* root){
if(root==nullptr)
return;
swap(root->left);
swap(root->right);
TreeNode* temp=root->left;
root->left=root->right;
root->right=temp;
}
TreeNode* invertTree(TreeNode* root) {
swap(root);
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) {
if(root==nullptr)
return root;
TreeNode* temp=root->left;
root->left=root->right;
root->right=temp;
invertTree(root->left);
invertTree(root->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) {
stack<TreeNode*> stk;
stk.push(root);
if(root==nullptr)
return root;
while(stk.empty()==false)
{
TreeNode* node=stk.top();
stk.pop();
TreeNode* temp=node->left;
node->left=node->right;
node->right=temp;
if(node->right!=nullptr)
stk.push(node->right);
if(node->left!=nullptr)
stk.push(node->left);
}
return root;
}
};
NC204 二叉树的最大宽度
采用层序遍历的方法,计算每层的个数放入到一个数组中,在数组中找出最大的数即可。
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return int整型
*/
int widthOfBinaryTree(TreeNode* root) {
// write code here
queue<TreeNode*> que;
que.push(root);
vector<int> nums;
nums.push_back(1);
while(que.empty()==false)
{
int size=que.size();
int count=0;
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
que.pop();
if(node->left!=nullptr)
{
que.push(node->left);
count++;}
if(node->right!=nullptr)
{
que.push(node->right);
count++;
}
}
nums.push_back(count);
}
int max=nums[0];
for(int i=0;i<nums.size();i++)
{
if(nums[i]>max)
max=nums[i];
}
return max;
}
};
110. 平衡二叉树
此时大家应该明白了既然要求比较高度,必然是要后序遍历。
递归三步曲分析:
1.明确递归函数的参数和返回值
参数:当前传入节点。
返回值:以当前传入节点为根节点的树的高度。
那么如何标记左右子树是否差值大于1呢?
如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。
所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了
2.明确终止条件
递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0
3.明确单层递归的逻辑
如何判断以当前传入节点为根节点的二叉树是否是平衡二叉树呢?当然是其左子树高度和其右子树高度的差值。
分别求出其左右子树的高度,然后如果差值小于等于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 getHeight(TreeNode* node){
if(node==nullptr)
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)
result=-1;
else
result=1+max(leftHeight,rightHeight);
return result;
}
bool isBalanced(TreeNode* root) {
return getHeight(root) == -1 ? false : true;
}
};
度为0的节点个数=度为2的节点个数+1
650

被折叠的 条评论
为什么被折叠?



