刚刚学完搜索这章 所以一开始面对关于树的题目 最先想到的也是DFS和BFS。但发现树更多的做法是回溯。写下来做过的题和思路以便后续复习。
树一直以来都不算我很熟悉的专题,今天看了一下,确实我对于树没有进行过专项的学习和总结。
这篇文章对应算法竞赛:入门到进阶的5.2 二叉树 P66
树的基础
树的基础知识是很重要的 这样在后续写代码的途中代码出错率能降低很多。(即使你的思路不是最优解。
树是非线性数据结构,它能很好的描述数据的层次关系。树形结构的现实场景很常见。例如,文件目录,书本的目录就是典型的树形特征。 二叉树是最常用的树形结构,特别适合程序设计,常常将一般的树转换为二叉树来处理。本章讲解二叉树的定义/遍历问题,以及二叉搜索树。
5.2.1 二叉树的存储
1. 二叉树的性质
二叉树的每个结点最多有俩个子节点,分别是左孩子/右孩子,以及它们为根的子树成为左子树和右子树。
二叉树的第i层最多有2^(i-1)个节点。如果每一层的结点数都是满的,那么它为满二叉树。
2. 二叉树的存储结构
二叉树一般由指针来实现,并指向左右节点。
struct node{
int val;
node* l, r
}
删除树
void deleteTree(TreeNode* root){
if(root == nullptr) return;
deleteTree(root->left);
deleteTree(root->right);
delete root;
}
单纯delete root会引发memory Leak.
5.2.2 二叉树的遍历 Tree Traversal
宽度优先搜索
深度优先搜索
94. Binary Tree Inorder Traversal
另: 在二叉搜索树中,中序遍历实现了排序功能,返回结果是有序排列。如果已知某棵二叉树的3种遍历,可以把这棵树构造出来,即“中序遍历 + 后续遍历” 或者 “中序遍历 + 先续遍历”,都能确认这棵树。
但是,如果不知道中序遍历,只有“先序遍历 + 后续遍历”,不能确认一棵树。
LeetCode 相关例题
实战演练
回溯
这道是很好的回溯思考题。因为我没有能够很好的处理左右子树的nullptr问题,也就是说对于题目的思路不够清晰所以出错。
class Solution {
TreeNode* prev = nullptr;
public:
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if(!root) return nullptr;
//在左子树中寻找
TreeNode* left = inorderSuccessor(root->left. p);
if(left) return left;
//如果前一个节点是目标节点,则当前节点为后继
if(prev == p) return root;
//更新当前节点
prev = root;
//在右子树中查找
TreeNode* right = inorderSuccessor(root->right, p);
if(right) return right;
return nullptr;
}
};
Time Complexity:O(n) Space Complexity: 最佳情况(平衡树): 空间复杂度 O(logn)最坏情况(非平衡树): 空间复杂度 O(log n)。
----To be continue