• 只需要思考每一个节点应该做什么,其他的不用你管,抛给二叉树遍历框架,递归会对所有节点做相同的操作。
  • 遇到一道二叉树的题目时的通用思考过程是:是否可以通过遍历一遍二叉树得到答案?如果不能的话,是否可以定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案? 如果需要用到子树信息, 一般使用后序遍历.

二叉树题目的递归(DFS)解法可以分两类思路:

  1. 第一类是遍历一遍二叉树得出答案:对应着 回溯算法核心框架
  2. 第二类是通过分解问题计算出答案:对应着 动态规划核心框架。

以求二叉树最大深度为例:

  • 解法一:遍历一遍二叉树

[简单] 104. 二叉树的最大深度

  • 解法二:分解问题。定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案

[简单] 104. 二叉树的最大深度

二叉树的解题思路就可以归类为上述两种思路:

  1. 是否可以通过遍历一遍二叉树得到答案
  2. 如果不能的话,是否可以定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案

构建二叉树

根据层序遍历序列 {1, 2, 3, -1, -1, 4, 5} 构建二叉树:-1 代表 nullptr
二叉树 - 图1

  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. using namespace std;
  5. struct TreeNode {
  6. int val;
  7. TreeNode* left;
  8. TreeNode* right;
  9. TreeNode() : val(0), left(nullptr), right(nullptr) {}
  10. TreeNode(int num) : val(num), left(nullptr), right(nullptr) {}
  11. };
  12. int main()
  13. {
  14. vector<int> nodeList = {1, 2, 3, -1, -1, 4, 5}; // -1 代表 nullptr
  15. TreeNode* root = new TreeNode(nodeList[0]);
  16. queue<TreeNode*> nodeQ;
  17. nodeQ.push(root);
  18. int idx = 1;
  19. while(!nodeQ.empty() && idx < nodeList.size())
  20. {
  21. TreeNode* cur = nodeQ.front();
  22. nodeQ.pop();
  23. if(nodeList[idx] != -1)
  24. {
  25. cur->left = new TreeNode(nodeList[idx]);
  26. nodeQ.push(cur->left);
  27. }
  28. if(idx + 1 < nodeList.size() && nodeList[idx + 1] != -1)
  29. {
  30. cur->right = new TreeNode(nodeList[idx + 1]);
  31. nodeQ.push(cur->right);
  32. }
  33. idx += 2;
  34. }
  35. while(!nodeQ.empty())
  36. nodeQ.pop();
  37. nodeQ.push(root);
  38. while(!nodeQ.empty())
  39. {
  40. int levelSize = nodeQ.size();
  41. for(int i = 0; i < levelSize; ++i)
  42. {
  43. TreeNode* cur = nodeQ.front();
  44. nodeQ.pop();
  45. cout << cur->val << " ";
  46. if(cur->left != nullptr)
  47. nodeQ.push(cur->left);
  48. if(cur->right != nullptr)
  49. nodeQ.push(cur->right);
  50. }
  51. cout << endl;
  52. }
  53. return 0;
  54. }