一. 二叉树
1.1 二叉树的最大深度
递归算法,使用前序遍历
int maxDepth(alice::TreeNode *root){
if(root == nullptr)
return 0;
int result = 1;
auto inner = [&result](const auto &inner, alice::TreeNode *root, int depth) -> void{
result = result > depth ? result : depth;
if(root->lchild)
inner(inner, root->lchild, depth+1);
if(root->rchild)
inner(inner, root->rchild, depth+1);
};
inner(inner, root, 1);
return result;
}
递归算法,使用后序遍历
int maxDepth(alice::TreeNode *root){
if(root == nullptr)
return 0;
int max_left = maxDepth(root->lchild);
int max_right = maxDepth(root->rchild);
int result = 1 + std::max(max_left, max_right);
return result;
}
非递归算法,使用层序遍历是最合适的,因为二叉树最大的深度就是二叉树的层数
int maxDepth(alice::TreeNode *root){
if(root == nullptr)
return 0;
int depth = 0;
std::queue<alice::TreeNode *> queue;
queue.push(root);
while(! queue.empty()){
++depth;
int queue_size = queue.size();
for(int i = 0; i < queue_size; ++i){
alice::TreeNode *node = queue.front();
queue.pop();
if(node->lchild)
queue.push(node->lchild);
if(node->rchild)
queue.push(node->rchild);
}
}
return depth;
}
1.2 二叉树的最小深度
递归算法,使用前序遍历
int minDepth(const alice::TreeNode *root){
if(root == nullptr)
return 0;
int result = INT_MAX;
auto inner = [&result](const auto &inner, const alice::TreeNode *root, int depth) -> void{
if(! root->lchild && ! root->rchild && result > depth)
result = depth;
if(root->lchild)
inner(inner, root->lchild, depth+1);
if(root->rchild)
inner(inner, root->rchild, depth+1);
};
inner(inner, root, 1);
return result;
}
非递归算法,使用层序遍历
int minDepth(const alice::TreeNode *root){
if(root == nullptr)
return 0;
int result = 1;
std::queue<const alice::TreeNode *> queue;
queue.push(root);
while(! queue.empty()){
int queue_size = queue.size();
for(int i = 0; i < queue_size; ++i){
const alice::TreeNode *front_node = queue.front();
queue.pop();
if(! front_node->lchild && ! front_node->rchild)
return result;
if(front_node->lchild)
queue.push(front_node->lchild);
if(front_node->rchild)
queue.push(front_node->rchild);
++result;
}
}
return result;
}
1.3 完全二叉树的结点个数
递归算法,采用后序遍历
int nodeNum(const alice::TreeNode *root){
if(root == nullptr)
return 0;
int left_num = nodeNum(root->lchild);
int rigth_num = nodeNum(root->rchild);
int result = 1 + left_num + rigth_num;
return result;
}
非递归算法,采用层序遍历
int nodeNum(const alice::TreeNode *root){
if(root == nullptr)
return 0;
int result = 0;
std::queue<const alice::TreeNode *> queue;
queue.push(root);
while(! queue.empty()){
int queue_size = queue.size();
for(int i = 0; i < queue_size; ++i){
const alice::TreeNode *front_node = queue.front();
queue.pop();
++result;
if(front_node->lchild)
queue.push(front_node->lchild);
if(front_node->rchild)
queue.push(front_node->rchild);
}
}
return result;
}
1.4 平衡二叉树
二叉树中任意结点的左、右子树高度差的绝对值不超过 1
bool isAVL(const alice::TreeNode *root){
if(root == nullptr)
return true;
auto inner = [](const auto &inner, const alice::TreeNode *root) -> int{
if(root == nullptr)
return 0;
int left_h = inner(inner, root->lchild);
if(left_h == -1)
return -1;
int right_h = inner(inner, root->rchild);
if(right_h == -1)
return -1;
if(std::abs(left_h - right_h) > 1)
return -1;
else
return 1 + std::max(left_h, right_h);
};
return inner(inner, root) == -1 ? false : true;
}
1.5 二叉树的所有路径
递归算法, 使用前序遍历
template <typename T>
void showVec(const std::vector<T> &vec){
std::cout << '{';
for(int i = 0; i < vec.size(); ++i){
std::cout << vec[i];
if(i != vec.size() - 1)
std::cout << ", ";
}
std::cout << '}';
}
std::vector<std::string> allPath(const alice::TreeNode *root){
std::vector<std::string> all_path;
if(root == nullptr)
return all_path;
auto inner = [&all_path](const auto &inner, const alice::TreeNode *root, std::vector<int> &path) -> void{
if(! root->lchild && ! root->rchild){
std::string str;
for(int i = 0; i < path.size(); ++i){
str += std::to_string(path[i]);
if(i != path.size() - 1)
str += " -> ";
}
all_path.emplace_back(str);
return;
}
if(root->lchild){
path.emplace_back(root->lchild->data);
inner(inner, root->lchild, path);
path.pop_back();
}
if(root->rchild){
path.emplace_back(root->rchild->data);
inner(inner, root->rchild, path);
path.pop_back();
}
};
std::vector<int> path;
path.emplace_back(root->data);
inner(inner, root, path);
return all_path;
}
非递归算法,使用前序遍历的模板
std::vector<std::string> allPath(const alice::TreeNode *root){
std::vector<std::string> all_path;
if(root == nullptr)
return all_path;
std::stack<const alice::TreeNode *> stack_node;
std::stack<std::string> stack_path;
stack_node.push(root);
stack_path.push(std::to_string(root->data));
while(! stack_node.empty()){
const alice::TreeNode *top_node = stack_node.top();
stack_node.pop();
std::string top_path = stack_path.top();
stack_path.pop();
if(! top_node->lchild && ! top_node->rchild){
all_path.push_back(top_path);
continue;
}
if(top_node->rchild){
stack_node.push(top_node->rchild);
stack_path.push(top_path + " -> " + std::to_string(top_node->rchild->data));
}
if(top_node->lchild){
stack_node.push(top_node->lchild);
stack_path.push(top_path + " -> " + std::to_string(top_node->lchild->data));
}
}
return all_path;
}
1.6 左叶子之和
对于节点 A,若左孩子不为空,且左孩子的左右孩子都为空,那么节点 A 的左孩子为左叶子
判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子
递归算法,采用先序遍历
int sumLLeaf(const alice::TreeNode *root){
if(! root)
return 0;
int res = 0;
auto inner = [&res](const auto &inner, const alice::TreeNode *root) -> void{
if(! root->lchild && ! root->rchild)
return;
if(root->lchild && ! root->lchild->lchild && ! root->lchild->rchild)
res += root->lchild->data;
if(root->lchild)
inner(inner, root->lchild);
if(root->rchild)
inner(inner, root->rchild);
};
inner(inner, root);
return res;
}
作业
实现左叶子之和的非递归算法