[dfs] 对称二叉树

建议在 洛谷 查看。


考虑如何求解树的对称性问题。


假如我们现在在 i i i 号结点,其左儿子为 l i l_i li,右儿子为 r i r_i ri

l i l_i li r i r_i ri 都为 − 1 -1 1,即都不存在,则以 i i i 为根的子树是对称的。

l i l_i li r i r_i ri 有一个为 − 1 -1 1,则以 i i i 为根的子树必定不是对称的。

剩下了 l i l_i li r i r_i ri 都不为 − 1 -1 1 的情况,即两棵子树都不为空。

i i i 是对称的,则 l i l_i li r i r_i ri 的子树大小必须相等(用来剪枝),并且 l [ l i ] l[l_i] l[li] r [ r i ] r[r_i] r[ri] 的子树相同, r [ l i ] r[l_i] r[li] l [ r i ] l[r_i] l[ri] 的子树相同。


如果递归中只记录一个变量,就不好处理。

在递归中记录两个变量,表示两边递归到的变量。

先判断为空的情况,再判断两个变量的 a a a 值是否相等,不是的话就一定不对称。

最后对于两棵子树不为空的情况,直接递归 ( l [ l i ] , r [ r i ] ) (l[l_i], r[r_i]) (l[li],r[ri]) ( r [ l i ] , l [ r i ] ) (r[l_i], l[r_i]) (r[li],l[ri])


如果加上大小的剪枝,就再写一个计算子树大小的 dfs 即可。

void dfs1(int x){//计算子树大小
	if(x == -1){
		return;
	}
	dfs1(l[x]);
	dfs1(r[x]);
	size[x] = 1 + size[l[x]] + size[r[x]];//自己 + 左子树 + 右子树
}
bool dfs2(int x, int y){
	if(size[x] != size[y]){//子树大小不相等
		return 0;
	}
	if(a[x] != a[y]){//值不相等
		return 0;
	}
	if((x == -1) && (y == -1)){//两个子树为空
		return 1;
	}
	if((x == -1) || (y == -1)){//子树有一个为空
		return 0;
	}
	return dfs2(l[x], r[y]) && dfs2(r[x], l[y]);//向下递归
}
int main(){
	dfs1(1);
	for(int i = 1; i <= n; ++ i){
		if(dfs2(i, i)){//根为 i 的子树是对称的
			ans = max(ans, size[i]);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值