二叉树相关题目
文章目录
一、前言
今天是关于二叉树的相关题目的剖析~
二、二叉树
2.1 树的相关知识
树的存储、二叉树的前、中、后序遍历(基于递归)以及层次遍历(基于队列)、特殊状态的二叉树(二叉平衡树、二叉搜索树等一般做题用不到)、并查集(后面单独讲)、哈夫曼树(做题基本用不到,本质是贪心)
2.2 思想
二叉树的题目多是基于递归的
要对以root为根的二叉树做一些操作或者判断(转化为对其左子树和右子树做相同的操作和判断)
cpp
f(root)
{
// 递归边界
// 递归体
if(root...)
{
...;
}
f(root->left);
f(root->right);
}
2.3 例题
2.3.1 leetcode
-
LCR 145.判断对称二叉树
轴对称 == 镜面对称
-
226.翻转二叉树
-
236.二叉树的最近公共祖先
2.3.2 洛谷
- P4913 【深基16.例3】二叉树深度
2.4 基础
-
注意有没有空树 的可能(边界条件),空树一般要特殊处理
-
树的某个节点是
i,那么它的左孩子是2 * i,右孩子是2 * i + 1 -
树结构定义
cppstruct TreeNode { int val; // 数据 TreeNode* left; TreeNode* right; } TreeNode* buildTree(int i) { if(i > n || a[i] == -1) // 越界了或者是空节点 { return NULL; } TreeNode* node = (TreeNode *)malloc(sizeof(TreeNode)); node->val = a[i]; node->left = buildTree(2 * i); node->right = buildTree(2 * i + 1); return node; } TreeNode* root = buildTree(1); // 1是指的下标 -
层次遍历
cppqueue<TreeNode*> q; q.push(root); TreeNode* x; while(!q.empty()) { x = q.front(); q.pop(); if(x != NULL) { printf("%d", x->val); if(x->left) { q.push(x->left); } if(x->right) { q.push(x->right); } } } -
前中后序遍历
cpp// 前序 void preorder(TreeNode *root, vector<int> &res) { if(root == NULL) { return; } res.push_back(root->val); preorder(root->left, res); preorder(root->right, res); } // 中序 void inorder(TreeNode* root, vector<int>& res) { if(root == NULL) { return; } inorder(root->left, res); res.push_back(root->val); inorder(root->right, res); } // 后序 void postorder(TreeNode* root, vector<int>& res) { if(root == NULL) { return; } postorder(root->left, res); postorder(root->right, res); res.push_back(root->val); } -
解题时学会使用简洁的引用版本(共享集合/答案)
cppvoid dfs(TreeNode* root, 集合(引用版本)) { ...; } // 主要函数 -
什么是叶子
cppif(node && node->left == NULL && node->right == NULL) { ans.push_back(node); }
三、小结
本篇结合灵神题单、洛谷官方书籍等以及自己的一些感受等~