前言
这里记录一下陈菜菜的刷题记录,主要应对25秋招、春招
个人背景
211CS本+CUHK计算机相关硕,一年车企软件开发经验
代码能力:有待提高
常用语言:C++
系列文章目录
第一天 数组 part01
第二天 数组 part02
第三天 链表 part01
第四天 链表 part02
第五天 休息
第六天 哈希表 part01
第七天:第三章 哈希表part02
第八天 :第四章 字符串part01
第九天 :第四章 字符串part02
第十天 :第五章 栈与队列part01
第十一天 :第五章 栈与队列part02
第十二天 :休息
第十三天 :第六章 二叉树part01
`
一、今日任务
● 理论基础
● 递归遍历 (必须掌握)
● 迭代遍历
● 统一迭代
● 层序遍历
二、详细布置
理论基础
1、C++中map、set、multimap,multiset的底层实现都是平衡二叉搜索树,所以map、set的增删操作时间时间复杂度是logn,注意这里没有说unordered_map、unordered_set,unordered_map、unordered_set底层实现是哈希表。
2、用数组来存储二叉树时,如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。
3、二叉树主要有两种遍历方式:
深度优先遍历
:先往深走,遇到叶子节点再往回走。
广度优先遍历
:一层一层的去遍历。
深度优先遍历
前序遍历(递归法,迭代法)
中序遍历(递归法,迭代法)
后序遍历(递归法,迭代法)
广度优先遍历
层次遍历(迭代法)
栈其实就是递归的一种实现结构,也就说前中后序遍历的逻辑其实都是可以借助栈使用递归的方式来实现的
。
而广度优先遍历的实现一般使用队列来实现,
这也是队列先进先出的特点所决定的,因为需要先进先出的结构,才能一层一层的来遍历二叉树。
递归遍历
每次写递归
,都按照这三要素来写:
确定递归函数的参数和返回值
:确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。确定终止条件
: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
3.确定单层递归的逻辑
: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
144.二叉树的前序遍历:
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
样例1:
输入:root = [1,null,2,3]
输出:[1,2,3]
样例2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[1,2,4,5,6,7,3,8,9]
样例3:
输入: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 preorder(TreeNode *t,vector<int> &result){
if(t==NULL)
return ;
else
result.push_back(t->val);
preorder(t->left,result);
preorder(t->right,result);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> re;
preorder(root,re);
return re;
}
};
144.二叉树的前序遍历:
给你二叉树的根节点 root ,返回它节点值的 后序 遍历。
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
样例1:
输入:root = [1,null,2,3]
输出:[3,2,1]
样例2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[4,6,7,5,2,9,8,3,1]
样例3:
输入: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 postorder(TreeNode* t,vector<int> &res){
if(t==NULL)
return ;
postorder(t->left,res);
postorder(t->right,res);
res.push_back(t->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
postorder(root,result);
return result;
}
};
94.二叉树的中序遍历:
给你二叉树的根节点 root ,返回它节点值的 中序 遍历。
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
样例1:
输入:root = [1,null,2,3]
输出:[1,3,2]
样例2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[1,2,4,5,6,7,3,8,9]
样例3:
输入: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 inorder(TreeNode* t,vector<int> &res){
if(t==NULL)
return;
inorder(t->left,res);
res.push_back(t->val);
inorder(t->right,res);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
inorder(root,result);
return 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:
/*void preorder(TreeNode *t,vector<int> &result){
if(t==NULL)
return ;
else
result.push_back(t->val);
preorder(t->left,result);
preorder(t->right,result);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> re;
preorder(root,re);
return re;
}*/
//迭代算法
vector<int> preorderTraversal(TreeNode* root){
vector<int> result;
stack<TreeNode*>st;
if(root!=NULL)
st.push(root);
while(!st.empty()){
TreeNode* node=st.top();
if(node!=NULL){
st.pop();
if(node->right)
st.push(node->right);
if(node->left)
st.push(node->left);
st.push(node);
st.push(NULL);
}
else{
st.pop();
node=st.top();
result.push_back(node->val);
st.pop();
}
}
return result;
}
};
102.二叉树的层序遍历
题目链接:LeetCode 102
文章讲解:代码随想录-102
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
样例1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
样例2:
输入:root = [1]
输出:[[1]]
样例3:
输入:root = []
输出:[]
提示
树中节点数目在范围 [0, 2000] 内
-1000 <= Node.val <= 1000
思路
用队列实现层序遍历。
实战
/**
* 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;
vector<vector<int>> result;
if(root!=NULL)
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);
}
return result;
}
};
总结
今天主要学习了二叉树的一系列操作,很难啊,树和图一直是我不太熟的内容。但是今天努力学习了迭代遍历树的算法,统一遍历太厉害了。明天早上起来再做一遍
加油,坚持打卡的第十天。