非科班学习算法day13 | LeetCode144:二叉树的前序遍历 ,Leetcode145: 二叉树的后序遍历,Leetcode97:二叉树的中序遍历 ,LeetCode589:N叉树的前序遍历,Leetcode102:二叉树的层序遍历 ,Leetcode199: 二叉树的右视图 ,Leetcode637: 二叉树的层平均值,Leetcode429: N叉树的层序遍历,Leetcode515: 在每个树行中找最大值,Leetcode116: 填充每个节点的下一个右侧节点指针
目录
10.Leetcode116: 填充每个节点的下一个右侧节点指针
介绍
包含LC的几道题目,还有相应概念的补充。
相关图解和更多版本:
代码随想录 (programmercarl.com)https://programmercarl.com/#%E6%9C%AC%E7%AB%99%E8%83%8C%E6%99%AF
一、基础概念补充:
1.递归的三个步骤
确定返回值和传入参数;
确定中止条件;
写一次递归的逻辑。
不要过分关注后面的过程,容易绕进去。
二、LeetCode题目
1.LeetCode144:二叉树的前序遍历
题目链接:144. 二叉树的前序遍历 - 力扣(LeetCode)
题目解析
分别采用递归和迭代方法给出,其中递归分为引用函数的递归和直接递归。
第一种递归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:
// 设置递归函数
vector<int> Traverasl(TreeNode* cur, vector<int>& vec) {
// 设置中止出口
if (cur == nullptr)
return vec;
// 递归体
vec.push_back(cur->val);
Traverasl(cur->left, vec);
Traverasl(cur->right, vec);
// 返回结果
return vec;
}
vector<int> preorderTraversal(TreeNode* root) {
// 创建vec
vector<int> result;
// 调用函数
return Traverasl(root, result);
}
};
第二种递归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:
vector<int> result;
vector<int> preorderTraversal(TreeNode* root)
{
//设置中止出口
if(root == nullptr) return result;
//迭代体
result.push_back(root->val); //中
preorderTraversal(root->left); //左边遍历
preorderTraversal(root->right); //右边遍历
//设置最终返回值
return result;
}
};
迭代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:
// 创建模拟栈
stack<TreeNode*> st;
// 创建结果vector
vector<int> result;
// 迭代函数
vector<int> preorderTraversal(TreeNode* root) {
// 插入根节点
if (root != nullptr)
st.push(root);
// 设置迭代条件
while (!st.empty()) {
// 记录栈顶
TreeNode* cur_node = st.top();
// 弹栈
st.pop();
// 中间节点进入结果vector
result.push_back(cur_node->val);
// 进栈该节点的左右子节点
if (cur_node->right != nullptr)
st.push(cur_node->right);
if (cur_node->left != nullptr)
st.push(cur_node->left);
// 弹栈操作开始迭代
}
return result;
}
};
2.Leetcode145:二叉树的后序遍历
题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)
题目解析
分别采用递归和迭代方法给出,其中递归分为引用函数的递归和直接递归。
第一种递归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:
// 创建递归函数
vector<int> Traversal(TreeNode* cur, vector<int>& vec) {
// 设置中止条件
if (cur == nullptr)
return vec;
// 递归体
Traversal(cur->left, vec);
Traversal(cur->right, vec);
vec.push_back(cur->val);
// 返回
return vec;
}
vector<int> postorderTraversal(TreeNode* root) {
// 创建结果函数
vector<int> result;
// 调用函数
return Traversal(root, result);
}
};
第二种递归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:
//创建vec
vector<int> result;
vector<int> postorderTraversal(TreeNode* root)
{
//设置中止出口
if(root == nullptr) return result;
//递归体
postorderTraversal(root->left);
postorderTraversal(root->right);
result.push_back(root->val);
//返回
return result;
}
};
迭代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:
// 创建模拟栈
stack<TreeNode*> st;
// 创建结果vector
vector<int> result;
vector<int> postorderTraversal(TreeNode* root) {
// 初始化
if (root != nullptr)
st.push(root);
// 迭代
while (!st.empty()) {
// 记录栈顶
TreeNode* cur_node = st.top();
// 弹栈
st.pop();
// 元素进入结果
result.push_back(cur_node->val);
// 加入左右子节点
if (cur_node->left != nullptr)
st.push(cur_node->left);
if (cur_node->right != nullptr)
st.push(cur_node->right);
}
reverse(result.begin(), result.end());
return result;
}
};
3.Leetcode97: 二叉树的中序遍历
题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)
题目解析
分别采用递归和迭代方法给出,其中递归分为引用函数的递归和直接递归。
第一种递归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:
// 创建递归函数
vector<int> Traversal(TreeNode* cur, vector<int>& vec) {
// 设置递归出口
if (cur == nullptr)
return vec;
// 递归体
Traversal(cur->left, vec);
vec.push_back(cur->val);
Traversal(cur->right, vec);
//
return vec;
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
return Traversal(root, result);
}
};
第二种递归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:
//创建返回值
vector<int> result;
vector<int> inorderTraversal(TreeNode* root)
{
if(root == nullptr) return result;
inorderTraversal(root->left);
result.push_back(root->val);
inorderTraversal(root->right);
return result;
}
};
注意点1:
4.Leetcode589: N叉树的前序遍历
题目链接:589. N 叉树的前序遍历 - 力扣(LeetCode)
题目解析
分别采用递归和迭代方法给出,其中递归分为引用函数的递归和直接递归。
递归C++代码如下:
/*
// 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> result;
vector<int> preorder(Node* root) {
// 创建中止出口
if (root == nullptr)
return result;
// 递归体
result.push_back(root->val);
for (auto child : root->children) {
preorder(child);
}
return result;
}
};
迭代c++代码如下:
/*
// 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:
stack<Node*> st;
vector<int> result;
vector<int> preorder(Node* root) {
if (root == nullptr)
return result;
st.push(root);
while (!st.empty()) {
Node* cur_node = st.top();
st.pop();
result.push_back(cur_node->val);
for (auto it = cur_node->children.rbegin();
it != cur_node->children.rend(); it++) {
st.push(*it);
//vector<Node*>::reverse_iterator
}
}
return result;
}
};
5.Leetcode102:二叉树的层序遍历
题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode)
题目解析
下面的题目用的都是层序遍历,非常相似,只是在处理的时候可能有不同的统计变量或者操作,这里直接给出代码。
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:
vector<vector<int>> levelOrder(TreeNode* root)
{
//建立数组接受结果
vector<vector<int>> result;
//建立控制队列
queue<TreeNode*>que;
//检验根节点是否为空
if(root != nullptr)
{
que.push(root);
}
//弹出控制队列的所有元素为止
while(!que.empty())
{
//创建当前层数组接受结果
vector<int> current_vec;
//记录当前层数元素数量
int size = que.size();
//设置循环弹出当前层数量的元素
for(;size > 0; size--)
{
//记录元素即将弹出元素
TreeNode* current_node = que.front();
//将该元素记录到current_vec
current_vec.push_back(current_node->val);
//弹出
que.pop();
//添加左右节点
if(current_node->left)
{
que.push(current_node->left);
}
if(current_node->right)
{
que.push(current_node->right);
}
}
//当前层弹出结束,更新队列长度
size = que.size();
//将当前队列添加到结果
result.push_back(current_vec);
}
return result;
}
};
6.Leetcode199: 二叉树的右视图
题目链接:199. 二叉树的右视图 - 力扣(LeetCode)
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:
vector<int> rightSideView(TreeNode* root)
{
//创建结果数列
vector<int> result;
//创建队列
queue<TreeNode*> que;
//插入根节点
if(root != nullptr) que.push(root);
//初始化层元素数量
int size = que.size();
//循环弹出节点
while(!que.empty())
{
for(int i = 0; i < size; i++)
{
//记录头部
TreeNode* cur_node = que.front();
//弹出
que.pop();
//当到达最后一个,单次判断
if(i == size - 1)
{
result.push_back(cur_node->val);
}
//添加左右节点
if(cur_node->left != nullptr) que.push(cur_node->left);
if(cur_node->right != nullptr) que.push(cur_node->right);
}
//更新
size = que.size();
}
return result;
}
};
7.Leetcode637: 二叉树的层平均值
题目链接:637. 二叉树的层平均值 - 力扣(LeetCode)
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:
vector<double> averageOfLevels(TreeNode* root)
{
//创建结果数组
vector<double> result;
//创建队列
queue<TreeNode*> que;
//插入根节点
if(root != nullptr) que.push(root);
//初始化层元素数量
int size = que.size();
//循环弹栈
while(!que.empty())
{
//初始化和
double sum = 0.0;
for(int i = 0; i < size; i++)
{
//记录当前节点信息
TreeNode* cur_node = que.front();
//更新和
sum += (double)cur_node->val;
//弹栈
que.pop();
//加入子节点
if(cur_node->left != nullptr) que.push(cur_node->left);
if(cur_node->right != nullptr) que.push(cur_node->right);
}
//计算平均值
double cur_avg = sum / size;
//更新size
size = que.size();
//下一循环已经
result.push_back(cur_avg);
}
return result;
}
};
8.Leetcode429: N叉树的层序遍历
题目链接:429. N 叉树的层序遍历 - 力扣(LeetCode)
C++代码如下:
/*
// 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>> result;
//建立队列
queue<Node*> que;
//插入根节点
if(root != NULL)
{
que.push(root);
}
//初始化size
int size = que.size();
//循环
while(!que.empty())
{
//建立当前层接收数组
vector<int> cur_vec;
while(size--)
{
//保存栈顶
Node* cur_node = que.front();
//插入结果
cur_vec.push_back(cur_node->val);
//弹栈
que.pop();
//遍历插入子节点
for(auto it:cur_node->children)
{
if(it)
{
que.push(it);
}
}
}
//更新
size = que.size();
result.push_back(cur_vec);
}
return result;
}
};
9.Leetcode515: 在每个树行中找最大值
题目链接:515. 在每个树行中找最大值 - 力扣(LeetCode)
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:
vector<int> largestValues(TreeNode* root)
{
//建立接受数组
vector<int> result;
//建立辅助队列
queue<TreeNode*> que;
//插入根节点
if(root != nullptr)
{
que.push(root);
}
//初始化数组长度
int size = que.size();
//循环
while(!que.empty())
{
vector<int> cur_vec;
while(size--)
{
//保留头部信息
TreeNode* cur_node = que.front();
//弹栈
que.pop();
//插入
cur_vec.push_back(cur_node->val);
//左右子节点
if(cur_node->left != nullptr) que.push(cur_node->left);
if(cur_node->right != nullptr) que.push(cur_node->right);
}
//更新size
size = que.size();
//max
auto it = max_element(cur_vec.begin(), cur_vec.end());
int vec_max = *it;
//max to re
result.push_back(vec_max);
}
return result;
}
};
10.Leetcode116: 填充每个节点的下一个右侧节点指针
题目链接:116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)
C++代码如下:
/*
// 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 != NULL) {
que.push(root);
}
// 初始化数组长度
int size = que.size();
// 设置循环
while (!que.empty()) {
while (size--) {
// 记录当前头节点
Node* cur_node = que.front();
// 弹栈
que.pop();
// 记录当前头节点
Node* cur_node2 = que.front();
// 设置指向
if (size == 0) {
cur_node->next = NULL;
} else {
cur_node->next = cur_node2;
}
if (cur_node->left)
que.push(cur_node->left);
if (cur_node->right)
que.push(cur_node->right);
}
// 更新size
size = que.size();
}
return root;
}
};
总结
打卡第13天,第一次看二叉树的时候哭了,坚持!!!