嵌入式软件常用面试题汇总之 C/C++ 语言相关(6)
C/C++之常考二叉树相关基础编程题汇总
嵌入式的笔试中编程题也会有基础的二叉树相关操作题,以下挑几道当时做过比较基础重要的,掌握了基本就能通关,至少掌握几种遍历的写法。参考的解法都是几年前自己做的了,也欢迎各位优化指正!
1.二叉树的层序遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 示例 2: 输入:root = [1] 输出:[[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:
vector<vector<int>> levelOrder(TreeNode* root)
{
vector<vector<int>> result;
vector<int> tmp;
if(root == NULL) return result;
queue<TreeNode*> T;
T.push(root);
int size = 0;
while(!T.empty())
{
size = T.size();
while(size)
{
root = T.front();
T.pop();
tmp.push_back(root->val);
if(root->left != NULL)
{
//tmp.push_back(root->left->val);
T.push(root->left);
}
if(root->right != NULL)
{
//tmp.push_back(root->right->val);
T.push(root->right);
}
--size;
}
result.push_back(tmp);
tmp.clear();
}
return result;
}
};
2.二叉树的前序遍历
给你二叉树的根节点 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] 提示:
|
参考解法:直接利用栈来完成,比较方便理解。
/**
* 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) {}
* };
*/
/*
二叉树的前序遍历是一种深度优先遍历方式,前序遍历的顺序是:
1.访问根节点。
2.前序遍历左子树。
3.前序遍历右子树。
下面的解法跟递归本质一样,不过是把栈给显示出来了。
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root)
{
stack<TreeNode*> TreeStack;
vector<int> result;
while(root != NULL || !(TreeStack.empty()))
{
while(root != NULL)
{
result.push_back(root->val);
TreeStack.push(root);
root = root->left;
}
root = TreeStack.top();
TreeStack.pop();
root = root->right;
}
return result;
}
};
3.二叉树的中序遍历
给定一个二叉树的根节点 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:
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> result;
stack<TreeNode*> TreeStack; //栈来辅助遍历
while(root != NULL || !(TreeStack.empty())) //确保了所有节点都会被访问到
{
while(root != NULL) //内部循环用于遍历到最左边的节点,将遍历路径中的所有节点压入栈中
{
TreeStack.push(root);
root = root->left;
}
//从栈中弹出一个节点,并将其值添加到结果向量中。这一步对应中序遍历中的“访问根节点”步骤。
root = TreeStack.top();
TreeStack.pop();
result.push_back(root->val);
//转向当前节点的右子树,继续下一轮遍历
root = root->right;
}
return result;
}
};
4.二叉树的后序遍历
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
示例 1:
输入:root = [1,null,2,3] 输出:[3,2,1] 示例 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:
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> result;
accessTree(result, root);
return result;
}
//方法一递归,递归的话注意要传引用进去,否则对副本起作用后又消失了
void accessTree(vector<int> &res, TreeNode* node)
{
if(node == NULL) return;
accessTree(res, node->left);
accessTree(res, node->right);
res.push_back(node->val);
}
};
//方法三
/* vector<int> postorderTraversal(TreeNode* root)
{
vector<int> result;
stack<TreeNode*> TreeStack;
TreeNode* preroot = NULL;
if(root == NULL ) return result;
while(root != NULL || !(TreeStack.empty()) )
{
while(root != NULL)
{
TreeStack.push(root);
root = root->left;
}
/*弹出一个,当其是否有右节点或右节点已经访问过,则可以访问这个结点,注意访问完后要把preroot置为它,然后结点置为null;如果不满足的话,则把这个结点压栈,然后变成它的右节点,再次进入上次的循环*/
/* root = TreeStack.top();
TreeStack.pop();
if(root->right == NULL || root->right == preroot)
{
result.push_back(root->val);
preroot = root ;
root = NULL;
}else
{
TreeStack.push(root);
root = root->right;
}
}
return result;
}
*/
5.二叉树的最大深度
给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:3 示例 2: 输入:root = [1,null,2] 输出: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) {}
* };
*/
/*方法
一:直接递归来实现,每次往左和右递归然后取那个大的,最后加一
二:配合队列来实现,每次进队列的是同一层的结点,每次处理完一批结点,让深度加1
*/
//方法二
class Solution {
public:
int maxDepth(TreeNode* root)
{
int depth = 0;
int size = 0; //每次队列中的个数,即该层节点数
queue<TreeNode*> T;
if(root == NULL) return 0;
T.push(root);
while(!T.empty())
{
size = T.size();
while(size)
{
root = T.front();
T.pop();
if(root->left != NULL)
{
T.push(root->left);
}
if(root->right != NULL)
{
T.push(root->right);
}
--size;
}
++depth;
}
return depth;
}
};
//方法一递归
/* int maxDepth(TreeNode* root)
{
if(root == NULL) return 0;
else return max(maxDepth(root->left),maxDepth(root->right))+1;
}
*/
6.对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3] 输出:true 示例 2:
输入:root = [1,2,2,null,3,null,3] 输出:false 提示:
|
解法参考:
/**
* 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 == NULL) return true;
return access(root->left,root->right);
}
bool access(TreeNode* l,TreeNode* r)
{
if(l == NULL && r == NULL) return true;
if(l == NULL || r == NULL) return false;
if(l->val != r->val) return false;
return access(l->left,r->right) && access(l->right,r->left);
}
};
//方法二
/*class Solution {
public:bool isSymmetric(TreeNode* root)
{
//从根节点的左右开始
TreeNode* u = root->left;
TreeNode* v = root->right;
//来个边界判断 不成立的话就开始双双进队列了
if(root == NULL || (u == NULL && v == NULL)) return true;
queue<TreeNode*> T;
T.push(u);
T.push(v);
while(!T.empty()) //循环的存放
{
u = T.front();
T.pop();
v = T.front();
T.pop();
/*判断条件要注意判断是否都为空,如果是返回跳出本次循环 再弹两个出来 如果一半为空或者不相等则返回false 都不会则继续进队列 全部循环结束返回真*/
/* if( u == NULL && v == NULL) continue; //注意不是用break
if( (u == NULL || v == NULL) || u->val != v->val ) return false;
T.push(u->left);
T.push(v->right);
T.push(u->right);
T.push(v->left);
}
return true;
}
};
*/
7.平衡二叉树
给定一个二叉树,判断它是否是 平衡二叉树
平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true 示例 2:
输入:root = [1,2,2,3,3,null,null,4,4] 输出:false 示例 3: 输入:root = [] 输出: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) {}
* };
*/
/*方法
一:自底向上递归解决,主要要想明白递归三要素,终止条件,处理过程,返回的值。 终止条件是root==null,处理过程是看高度差是否大于1,是的话返回负一。
二:自顶向下递归解决,好处是容易理解,坏处是重复调用,复杂度高
*/
class Solution {
public:
bool isBalanced(TreeNode* root)
{
if(root == NULL) return true;
else
{ return abs(depth(root->left)-depth(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right);
}
}
int depth(TreeNode* root)
{
if(root == NULL) return 0;
else return max(depth(root->left),depth(root->right))+1;
}
};
//自底向上递归
/*class Solution {
public:
bool isBalanced(TreeNode* root)
{
if(root == NULL) return true;
return helper(root) != -1;
}
int helper(TreeNode* root)
{
if(root == NULL) return 0;
int left = helper(root->left);
int right = helper(root->right);
if( left == -1 || right == -1 || abs(left-right)>1 )
{
return -1;
}
return max(left,right)+1;
}
};
*/
8.翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1] 示例 2:
输入:root = [2,1,3] 输出:[2,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:
TreeNode* invertTree(TreeNode* root)
{
if(root == NULL) return root;
stack<TreeNode*> T;
TreeNode* result = root;
T.push(root);
int size = 0;
while(!T.empty())
{
size = T.size();
while(size)
{
root = T.top();
T.pop();
TreeNode* tmp = root->left;
root->left = root->right;
root->right = tmp;
if(root->left != NULL)
{
T.push(root->left);
}
if(root->right != NULL)
{
T.push(root->right);
}
--size;
}
}
return result;
}
};
//直接递归
/*class Solution {
public:
TreeNode* invertTree(TreeNode* root)
{
if(root == NULL) return root;
invertTree(root->left);
invertTree(root->right);
TreeNode* tmp = root->left;
root->left = root->right;
root->right = tmp;
return root;
}
};
*/
#23届找工作求助阵地##二叉树##笔面试##嵌入式##嵌入式软件实习#该专栏是我整理的一些嵌入式软件笔面试常见的题目,在有一定计算机基础上,再过一遍该专栏的内容,对应届生校招来说基本上笔面试就没什么问题了! 有任何疑问可随时与我联系,一起交流一起进步。













查看3道真题和解析