嵌入式软件常用面试题汇总之 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届找工作求助阵地##二叉树##笔面试##嵌入式##嵌入式软件实习#
该专栏是我整理的一些嵌入式软件笔面试常见的题目,在有一定计算机基础上,再过一遍该专栏的内容,对应届生校招来说基本上笔面试就没什么问题了! 有任何疑问可随时与我联系,一起交流一起进步。