1. 前言
- 看到本题后,考虑使用前中后哪种遍历
- 确认递归函数是否携带返回值
- 运算符
&&
的逻辑短路的特性
2. 题目
已知两颗二叉树B1和B2,算法f52判断B1和B2是否相似,相似则返回1,否则返回0。如果B1和B2均为空树,则两棵树相似。如果B1和B2非空且B1的左右子树与B2的左右子树分别相似。则两棵树相似。
3. 题解思路
- 确定遍历对象
两棵未知形状的树,且由题意,两棵空树一定相似。
if (NULL == t1 && NULL == t2) { // 规范了空节点的比较,相似的二叉树,空节点的位置和数量总一致, 空节点一定被同时访问到。
return 1;
}
if (t1 && t2) { // 判断相似的逻辑简化,用逻辑运算符代替
return 1;
}
-
先序遍历一定可以
根据题意题意:比较左右子树,首次访问根节点就触发对比逻辑,之后依次以左右子树为根继续触发对比逻辑。 -
设置返回值
题目很明确需要返回0或1,语义是相似或不相似。如何借用这个语义减少遍历深度?
// 两个节点相似后,判断节点的左孩子是否相似,再判断又孩子时候相似
// 任意一个条件不相似,不再递归往下查,同时向上返回0,则上层所有调用层的if语句含有0,实现逻辑短路,减少判断。比如节点的左子树已经不相似了,不会再查右子树了。
if (t1 && t2 && f52(t1->lchild, t2->lchild) && f52(t1->rchild, t2->rchild)) {
return 1;
} else {
return 0;
}
4. 代码
int f52(BiTree t1, BiTree t2) {
if (NULL == t1 && NULL == t2) {
return 1;
} else if (t1 && t2 && f52(t1->lchild, t2->lchild) && f52(t1->rchild, t2->rchild)) {
return 1;
} else {
return 0;
}
}
5. 后记
如果一个算法支持先序遍历,尝试使用返回值进行 “逻辑短路”,借以减少平均递归深度和判断次数。