- 基本概念
- 104. 二叉树的最大深度">104. 二叉树的最大深度
- 144. 二叉树的前序遍历(mdium)">144. 二叉树的前序遍历(mdium)
- 94. 二叉树的中序遍历(mdium)">94. 二叉树的中序遍历(mdium)
- 145. 二叉树的后序遍历(hard)">145. 二叉树的后序遍历(hard)
- 102. 二叉树的层序遍历">102. 二叉树的层序遍历
基本概念
深度优先搜索:Depth First Search, DFS
广度优先搜索:Breadth First Search, BFS
路径搜索的两个基本思路,一个以深度优先(一条路走到黑),另一个以广度优先(每个分岔口都走一下看看)
主要可以参考二叉树的遍历:
- 前序遍历、中序遍历、后序遍历属于深度优先搜索DFS
- 层次遍历属于广度优先搜索BFS
104. 二叉树的最大深度
方法一:递归
class Solution {public:int maxDepth(TreeNode* root) {if(root==NULL){return 0;}else{int left_height = maxDepth(root->left);int right_height = maxDepth(root->right);return max(left_height,right_height)+1;}}};
方法二:迭代
我们还可以在栈的帮助下将上面的递归转换为迭代。
我们的想法是使用 DFS 策略访问每个结点,同时在每次访问时更新最大深度。
所以我们从包含根结点且相应深度为 1 的栈开始。然后我们继续迭代:将当前结点弹出栈并推入子结点。每一步都会更新深度
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/class Solution {public:int maxDepth(TreeNode* root) {queue<TreeNode*>q;//队列, q是队列对象if(root!=nullptr){//用nullptr 不用NULL, 这样不会出现构造函数int 空,精确为空指针q.push(root); //此时q队列 size为1,只有根节点}int depth = 0; //初始depthwhile(q.size()!=0){ //遍历我们的队列int n = q.size(); // n等于 队列里面元素的个数for(int i=0; i<n; i++){ // 把队列里面每个元素都进行处理TreeNode* tr = q.front(); //把队列第一个元素赋值给trq.pop(); //把队列第一个元素弹出, 先进先出原则if(tr->left!=nullptr){ //如果该元素有左子结点,则把左子结点推入队列qq.push(tr->left);}if(tr->right!=nullptr){//如果有右子结点,则把右子结点推入队列,q.push(tr->right);} //for循环会把本层树的所有结点都作为root遍历他们各自的左右子,然后把该层结点都弹出(在if之前弹出, 弹出前把该元素赋值给tr,每次tr都会更新)}depth++;//一层处理完,depth++, 深度+1 , 非常好理解}//直到都没有左右子结点, q则没有push元素进来了,则跳出,返回depthreturn depth;}};
144. 二叉树的前序遍历(mdium)
方法一:递归
class Solution {public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;preorder(root,result);return result;}void preorder(TreeNode* root, vector<int> &result){if(root){result.push_back(root->val);preorder(root->left,result);preorder(root->right,result);}}};
方法二:迭代
vector<int> preorderTraversal(TreeNode* root) {vector<int> res;// 空树if(root == NULL)return res;// 开始遍历stack<TreeNode*> stack;stack.push(root);while(!stack.empty()){// 取出栈顶root = stack.top();stack.pop();// 右结点先入栈(后访问)if(root->right != NULL)stack.push(root->right);// 左节点后入栈(先访问)if(root->left != NULL)stack.push(root->left);// 访问res.push_back(root->val);}return res;
94. 二叉树的中序遍历(mdium)
方法一:递归
void inorder(TreeNode* root, vector<int> &result){if(root != NULL){inorder(root->left, result);result.push_back(root->val); // !!!inorder(root->right, result);}}vector<int> inorderTraversal(TreeNode* root) {vector<int> result;inorder(root, result);return result;}
方法二:迭代
vector<int> inorderTraversal(TreeNode* root) {vector<int> res;// 空树if(root == NULL)return res;// 开始遍历stack<TreeNode*> stack;do{// 找到以root为根的子树的最左节点while(root != NULL){stack.push(root);root = root->left;}// 以root为根的子树的最左节点如果存在if(!stack.empty()){// 弹出栈顶root = stack.top();stack.pop();// 访问res.push_back(root->val);// 进入右结点root = root->right;}}while(root != NULL || !stack.empty());// 返回结果return res;}
145. 二叉树的后序遍历(hard)
左->右->中——这个访问顺序不易实现,需要记录已访问的节点
反序遍历(中->右->左)+翻转结果是一种作弊解法,并不是真正意义上的后序遍历
https://leetcode-cn.com/problems/binary-tree-postorder-traversal
可以与前序遍历比较一下——
- 每次循环取出栈顶的时候不直接出栈,只有左右节点都访问过了才能出栈
- 如果左/右节点未访问过,才会进入对应分支
- 只有左右节点都访问过了或者不存在,才能访问当前节点
方法一:递归
class Solution {public:vector<int> postorderTraversal(TreeNode* root) {vector<int> result;postorder(root,result);return result;}void postorder(TreeNode* root, vector<int>& result){if(root!=NULL){postorder(root->left,result);postorder(root->right,result);result.push_back(root->val);}}};
方法二:迭代
// 可以根前序遍历比较一下vector<int> postorderTraversal(TreeNode* root) {vector<int> res;unordered_set<TreeNode*> visited;// 空树if(root == NULL)return res;// 开始遍历stack<TreeNode*> stack;stack.push(root);while(!stack.empty()){bool left_visited = true, right_visited = true;// 取出栈顶(但不弹出)root = stack.top();// 如果右结点未访问,则入栈(先入栈后访问)if(root->right != NULL && visited.find(root->right) == visited.end()){right_visited = false;stack.push(root->right);}// 如果左节点未访问,则入栈(后入栈先访问)if(root->left != NULL && visited.find(root->left) == visited.end()){left_visited = false;stack.push(root->left);}// 如果左右节点都访问过了,那么可以访问本节点if(left_visited && right_visited){visited.insert(root);res.push_back(root->val);stack.pop();}}return res;}
102. 二叉树的层序遍历
方法一:宽度优先搜索
- 首先根元素入队
当队列不为空的时候
- 求当前队列的长度 si_s__i
依次从队列中取 si_s__i 个元素进行拓展,然后进入下一次迭代
class Solution {public:vector<vector<int>> levelOrder(TreeNode* root) {vector <vector <int>> ret;if (!root) return ret;queue <TreeNode*> q;q.push(root);while (!q.empty()) {int currentLevelSize = q.size();ret.push_back(vector <int> ());for (int i = 1; i <= currentLevelSize; ++i) {auto node = q.front(); q.pop();ret.back().push_back(node->val);if (node->left) q.push(node->left);if (node->right) q.push(node->right);}}return ret;}};
