二叉树的基本定义
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
例题
二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
返回它的最大深度 3 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
法一:自顶向下递归
自顶向下的方法,注意depth 无需添加 引用符号,因为并未将depth 本身传入下一个函数,而是申请了一个新空间存储depth+1,然后存入下一个函数。
class Solution {
public:
int maxDepth(TreeNode* root) {
int depth=1;
int ans=0;
countDepth(root, depth, ans);
return ans;
}
void countDepth(TreeNode* root,int depth, int& ans){//有个const
if (root==NULL) return;
ans = max(ans, depth);
countDepth(root->left, depth+1,ans);
countDepth(root->right, depth+1,ans);
}
};
法二:自下向上递归
class Solution {
public:
int maxDepth(TreeNode* root)
{
if (root != nullptr)
{
return max(maxDepth(root->left) + 1, maxDepth(root->right) + 1);
}
else
{
return 0;
}
}
};
中序遍历
法一:递归实现
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> list;
inorder(root, list);
return list;
}
void inorder(TreeNode* root,vector<int> &list)
{
if (root != NULL)
{
inorder(root->left, list);
list.push_back(root->val);
inorder(root->right, list);
}
}
};
前序遍历
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> list;
preorder(root, list);
return list;
}
void preorder(TreeNode* root,vector<int> &list)
{
if (root != NULL)
{
list.push_back(root->val);
preorder(root->left, list);
preorder(root->right, list);
}
}
};
后序遍历
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> list;
postorder(root, list);
return list;
}
void postorder(TreeNode* root,vector<int> &list)
{
if (root != NULL)
{
postorder(root->left, list);
postorder(root->right, list);
list.push_back(root->val);
}
}
};
层次遍历
队列实现法一。
队列中入队一个层次结束节点以判断当前遍历层数
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode*> nodequeue;
vector<vector<int>> res;
TreeNode* floorend = new TreeNode(-1);
if (root)
{
TreeNode* pointer = root;
nodequeue.push(pointer);
nodequeue.push(floorend);
}
int f = 0; //当前遍历的层
while(!nodequeue.empty())
{
TreeNode* tmp = nodequeue.front();
nodequeue.pop();
int data = tmp->val;
if (tmp == floorend) //层次判断节点,则不做任何处理
{
f++;
if (nodequeue.empty())
break;
//层数加1
nodequeue.push(floorend); //层次判断节点再次放到下一层的尾部
}
else if (res.size()<=f)
{
res.push_back(vector<int> {});
}
else
{
res[f].push_back(data);
}
if (tmp->left)
nodequeue.push(tmp->left);
if (tmp->right)
nodequeue.push(tmp->right);
}
reverse(res.begin(), res.end());
return res;
}
};
队列实现法二
当遍历完一层厚,队列中的剩余元素个数则是下一层的个数。
因此对每一层遍历前,是已知下一层元素个数的,可以使用循环按层遍历。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(!root) return res;
queue<TreeNode*> qu;
qu.push(root);
while(!qu.empty())
{
vector<int> tmp;
int len=qu.size();
for(int i=0;i<len;i++){
TreeNode* node=qu.front();
qu.pop();
tmp.push_back(node->val);
if(node->left) qu.push(node->left);
if(node->right) qu.push(node->right);
}
res.push_back(tmp);
}
return res;
}
};
先序遍历简洁实现:
C++,应该是最短的代码了。
层序遍历一般来说确实是用队列实现的,但是这里很明显用递归前序遍历就能实现呀,而且复杂度O(n)。。。
要点有几个:
利用depth变量记录当前在第几层(从0开始),进入下层时depth + 1;
如果depth >= vector.size()说明这一层还没来过,这是第一次来,所以得扩容咯;
因为是前序遍历,中-左-右,对于每一层来说,左边的肯定比右边先被遍历到,实际上后序中序都是一样的。。。
遍历时加入层数,直接把元素放入对应层的vector中。
代码如下:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
pre(root, 0, ans);
return ans;
}
void pre(TreeNode *root, int depth, vector<vector<int>> &ans) {
if (!root) return ;
if (depth >= ans.size())
ans.push_back(vector<int> {});
ans[depth].push_back(root->val);
pre(root->left, depth + 1, ans);
pre(root->right, depth + 1, ans);
}
};
验证二叉搜索树
官方题解:
https://leetcode-cn.com/problems/validate-binary-search-tree/solution/yan-zheng-er-cha-sou-suo-shu-by-leetcode/
法一:
利用二叉搜索树的特点,中序遍历后为有序数组来检查二叉树的有效性。
缺点:需要遍历整个二叉树才能知道是否有效。
优化方法:一边遍历二叉树,一边检查数组是否符合条件。
class Solution {
public:
bool isValidBST(TreeNode* root) {
bool ans = true;
vector<int> inorderlist;
inorderlist = inorderTraversal(root);
if (inorderlist.size() > 0)
for (int i = 1; i < inorderlist.size(); i++)
{
if (inorderlist[i - 1] >= inorderlist[i])
{
ans = false;
break;
}
}
return ans;
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> list;
inorder(root, list);
return list;
}
void inorder(TreeNode* root, vector<int>& list)
{
if (root != NULL)
{
inorder(root->left, list);
list.push_back(root->val);
inorder(root->right, list);
}
}
};
对称二叉树
递归实现方法:
定义一个递归函数,同时搜索左右两个子树,搜索的同时,判断元素是否一致。
关键点:
1、注意设定递归结束的边界条件
2、一个递归函数可以同时递归搜索两个不同树
class Solution {
public:
bool isSymmetric(TreeNode* root) { //迭代实现的方案
return ismirror(root, root);
}
bool ismirror(TreeNode*left_node, TreeNode*right_node) //左中右遍历
{
if (!left_node &&!right_node)
{
return true;
}
if (left_node && right_node)
{
if (left_node->val == right_node->val)
return ismirror(left_node->left, right_node->right) && ismirror(left_node->right, right_node->left);
}
return false;
}
};
迭代实现方法
待补充
将有序数组转换为二叉搜索树
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5