二叉树
作为单链表的升级版,我们通常接触的树都是二叉树(binary tree),即每个节点最多有两个子节点;
可以看出,其与链表的主要差别就是多了一个子节点的指针。
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x):val(x),left(NULL),right(NULL) {}
};
104.求一个二叉树的最大深度;
Input:
3
9 20
15 7
Output:3
int maxDepth(TreeNode* root){
if(!root) return 0;
int l=1+maxDepth(root->left);
int r=1+maxDepth(root->right);
return l>r ? l:r;
}
110.平衡二叉树
题目:判断一个二叉树是否平衡。树平衡的定义是,对于树上的任意节点,其两侧节点的最大深度差值不得大于1
题解:解法类似于求树的最大深度,但有两个不同的地方:一是我们需要先处理树的深度再进行比较,二是如果我们在处理子树时发现其已经不平衡了,
则可以返回一个-1,使得所有其长辈节点可以避免多余的判断(本题的判断比较简单,做差后取绝对值即可;但如果此处是一个开销较大的比较过程,
则避免重复判断可以节省大量的计算时间)。
bool isBalanced(TreeNode* root){ //主函数
return helper(root) != -1;
}
int helper(TreeNode* root){
if(!root){
return 0;
}
int left = helper(root->left); //递归
int right = helper(root->right); //递归
if(left == -1 || right == -1 || abs(left - right) > 1){ //abs取绝对值函数是重点
return -1;
}
return 1+max(left, right);
}
101.对称二叉树
题目描述:判断一个二叉树是否对称
输入输出:输入是一个二叉树,输出一个布尔值,表示该树是否对称
Input:
1
2 2
3 4 4 3
Output:true
题解:判断一个树是否对称等价于判断左右子树是否对称,笔者一般习惯将判断两个子树是否相等或对称的题的解法叫做“四步法”:
1.如果两个子树都为空指针,则它们相等或对称
2.如果两个子树只有一个为空指针,则它们不相等或不对称
3.如果两个子树根节点的值不相等,则它们不相等或不对称
4.根据相等或对称要求,进行递归处理
//主函数
bool isSymmetric(TreeNode *root){
return root? isSymmetric(root->left, root->right):true;
}
//辅函数
bool isSymmetric(TreeNode* left, TreeNode* right){
if(!left && !right){
return true;
}
if(!left || !right){
return false;
}
if(left->val != right->val){
return false;
}
return isSymmetric(left->left, right->right) && isSymmetric(left->right, right->left); //false && false 为 false
}
637.二叉树的层平均值
题目描述:给定一个二叉树,求每一层的节点值的平均数。
输入输出样例:
输入是一个二叉树,输出是一个一位数组,表示每层节点值的平局数。
Input:
3
9 20
15 7
Output:[3,14.5,11]
题解:利用广度优先搜索(一般用queue结构处理 empty()、push()、pop()、front()函数),我们可以很方便的求取每层的平均值。
queue 先进先出
vector<double> averageOfLevels(TreeNode* root){
vector<double> ans; //返回值
if(!root){ //异常判断
return ans;
}
queue<TreeNode*> q; //定义队列
q.push(root);
while (!q.empty()){
int count = q.size(); //count结合queue先进先出
double sum=0;
for(int i=0; i<count; ++i){
TreeNode* node = q.front(); //取值
q.pop(); //pop
sum += node->val; //累加
if(node->left){ //左子树
q.push(node->left);
}
if(node->right){ //右子树
q.push(node->right);
}
}
ans.push_back(sum/count);
}
return ans;
}
144.二叉树的前序遍历
题目描述:不使用递归,实现二叉树的前序遍历。
输入输出样例:输入一个二叉树,输出一个数组,为二叉树前序遍历的结果
Input:
1
2
3
Output:[1,2,3]
题解:因为递归的本质是栈调用,因此我们可以通过栈来实现前序遍历。注意入栈的顺序。
栈:可以想象成一个“羽毛球筒”或“子弹夹”,后进先出
栈数据结构名为stack top()、push()、pop()、empty()
前中后序遍历,指的是root节点的位置;子节点先左后右
vector<int> preorderTraversal(TreeNode* root){
vector<int> ret;
if(!root){
return ret;
}
stack<TreeNode*> s;
s.push(root);
while(!s.empty()){
TreeNode* node = s.top();
s.pop();
ret.push_back(node->val);
if(node->right){
s.push(node->right); //先右后左,保证左子树先遍历
}
if(node->left){
s.push(node->left);
}
}
return ret;
}
类型:
- 贪心算法
- 双指针
- 二分查找
- 排序算法
- 二维数组的搜索
- 动态规划
- 数据结构-stl
- 字符串比较、匹配
- 链表
- 二叉树