算法学习——LeetCode力扣二叉树篇4
222. 完全二叉树的节点个数
222. 完全二叉树的节点个数 - 力扣(LeetCode)
描述
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
示例
示例 1:
输入:root = [1,2,3,4,5,6]
输出:6
示例 2:
输入:root = []
输出:0
示例 3:
输入:root = [1]
输出:1
提示
- 树中节点的数目范围是[0, 5 * 104]
- 0 <= Node.val <= 5 * 104
- 题目数据保证输入的树是 完全二叉树
进阶
遍历树来统计节点是一种时间复杂度为 O(n) 的简单解决方案。你可以设计一个更快的算法吗?
代码解析
递归法–普通二叉树
/**
* 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:
int getNoteNum(TreeNode* cur)
{
if(cur==nullptr) return 0;
int left_num = getNoteNum(cur->left);
int right_num = getNoteNum(cur->right);
return 1 + left_num + right_num;
}
int countNodes(TreeNode* root) {
if(root==nullptr) return 0;
return getNoteNum(root);
}
};
递归法–完全二叉树
完全二叉树节点数公式:2^树的高度(深度+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:
int getnodenum(TreeNode* cur)
{
if(cur==nullptr) return 0 ;
TreeNode* left_tree = cur->left , *right_tree = cur->right;
int left_tree_num=0 , right_tree_num=0;
//分别结算左右树的深度是否一样,一样则是完全二叉树
while(left_tree!=nullptr)
{
left_tree = left_tree->left;
left_tree_num++;
}
while(right_tree!=nullptr)
{
right_tree = right_tree->right;
right_tree_num++;
}
if(left_tree_num == right_tree_num )
{
//完全二叉树节点数量的公式是2^(树的高度)-1
// return (2<<left_tree_num) - 1;
// left_tree_num是树的深度,要+1
return pow(2,left_tree_num+1) - 1;
}else
{
return 1 + getnodenum(cur->left) + getnodenum(cur->right) ;
}
}
int countNodes(TreeNode* root) {
if(root ==nullptr) return 0;
return getnodenum(root);
}
};
110. 平衡二叉树
110. 平衡二叉树 - 力扣(LeetCode)
描述
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 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
提示
- 树中的节点数在范围 [0, 5000] 内
- -104 <= Node.val <= 104
代码解析
求二叉树的深度和高度
深度:前序遍历
- 深度从根节点往下找,在递归栈增加的时候计算
高度:后序遍历 - 高度从叶子节点网上找,在递归栈减少的时候计算
/**
* 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:
//计算树的高度,后序遍历。当不是平衡二叉树(左右子树高度最多差1)的时候返回-1
int get_tree_height(TreeNode* cur)
{
if(cur==nullptr) return 0;
int left_height = get_tree_height(cur->left);
if(left_height == -1) return -1;//如果左子树不是平衡二叉树,整个树也不是平衡二叉树
int right_height =get_tree_height(cur->right);
if(right_height == -1) return -1;//如果右子树不是平衡二叉树,整个树也不是平衡二叉树
//两个子树是平衡二叉树,但是不确定整个树是不是平衡二叉树,计算两个树的高度差
//如果高度差大于1,则不是平衡二叉树。如果高度差是0或者1,则平衡二叉树的高度是最高子树加上根节点1
return abs(left_height - right_height) > 1 ? -1 : 1+max(left_height , right_height);
}
bool isBalanced(TreeNode* root) {
if(root == nullptr) return true;
return get_tree_height(root)== -1 ? false:true;
}
};
257. 二叉树的所有路径
257. 二叉树的所有路径 - 力扣(LeetCode)
描述
给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例
示例 1:
输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]
示例 2:
输入:root = [1]
输出:[“1”]
提示
- 树中节点的数目在范围 [1, 100] 内
- -100 <= Node.val <= 100
代码解析
递归法(非回溯,浪费内存)
直接递归字符串,每一次递归都产生一个新字符串。没有回溯的过程,浪费空间。
/**
* 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<string> result;
void get_road(TreeNode* cur , string &s)
{
if(cur == nullptr) return;
s += to_string(cur->val);
if(cur->left == nullptr && cur->right == nullptr )
{
result.push_back(s);
return;
}else if(cur->left != nullptr && cur->right == nullptr )
{
s += "->";
string s1 =s;
get_road(cur->left ,s1);
}else if (cur->left == nullptr && cur->right != nullptr )
{
s += "->";
string s1 =s;
get_road(cur->right ,s1);
}else
{
s += "->";
string s1 =s;
string s2 =s;
get_road(cur->left ,s1);
get_road(cur->right ,s2);
}
return;
}
vector<string> binaryTreePaths(TreeNode* root) {
string s;
get_road(root ,s);
return result;
}
};
递归回溯法
使用一个数组来保存路径数据,然后在转换成字符串。
效率略低,充分体现回溯的思想。
/**
* 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:
void get_road(TreeNode* cur , vector<string> &result , vector<int> &path)
{
if(cur == nullptr) return;
path.push_back(cur->val);
if(cur->left == nullptr && cur->right == nullptr )
{
string tmp;
for(int i=0 ; i < path.size()-1 ;i++ )
{
tmp += to_string(path[i]);
tmp += "->";
}
tmp += to_string(path[path.size()-1]);
result.push_back(tmp);
return;
}
if(cur->left != nullptr )
{
get_road(cur->left,result,path);
path.pop_back();
}
if(cur->right != nullptr)
{
get_road(cur->right,result,path);
path.pop_back();
}
return;
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
vector<int> path;
if(root == nullptr) return result;
get_road(root ,result , path);
return result;
}
};
递归回溯(精简版)
不使用数组进行纪录,直接进行字符串回溯
/**
* 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:
void get_road(TreeNode* cur , vector<string> &result , string path)
{
if(cur == nullptr) return;
path += to_string(cur->val);
if(cur->left == nullptr && cur->right == nullptr )
{
result.push_back(path);
return;
}
if(cur->left != nullptr )
{
get_road(cur->left,result, path + "->");
}
if(cur->right != nullptr)
{
get_road(cur->right,result, path + "->");
path.pop_back();
}
return;
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
string path;
if(root == nullptr) return result;
get_road(root ,result , path);
return result;
}
};
404. 左叶子之和
404. 左叶子之和 - 力扣(LeetCode)
描述
给定二叉树的根节点 root ,返回所有左叶子之和。
示例
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
提示
- 节点数在 [1, 1000] 范围内
- -1000 <= Node.val <= 1000
代码解析
/**
* 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:
int result=0;
void left_sum(TreeNode* cur)
{
if(cur==nullptr) return ;
//判断左子叶
if(cur->left!=nullptr&&cur->left->left==nullptr&&cur->left->right==nullptr)
result += cur->left->val;
left_sum(cur->left);
left_sum(cur->right);
}
int sumOfLeftLeaves(TreeNode* root) {
left_sum(root);
return result;
}
};