递归法:
对于递归,很多新手就是一看就懂,一写就废,(我也是这样,哈哈哈),自己也做一些用递归解决的题目,目前自己对递归的理解:
首先我们要了解递归四部曲:
1、确定递归的参数和返回值
2、确定递归终止条件
3、明确递归函数要实现怎么养的一个功能(单层递归的逻辑)
4、调用自身
回到对称二叉树这个问题,要判断对称二叉树,首先判断根节点的左子树和右子树是否相同,但要判断左子树和右子树是否相同,就又要判断左子树的左子树和右子树的右子树,左子树的右子树和右子树的左子树是否相同,想到这,我们就可以明确递归函数的返回值和函数内部的功能实现,我们上一步的结果需要借助下一步的结果来判断,所以,我们应该把函数本身作为返回值返回给上一层。
动态图如下:
递归代码如下:
public boolean isSymmetric(TreeNode root){
if(root == null){
throw new RuntimeException("根节点为空!");
}
return isMirror(root,root);
}
public boolean isMirror(TreeNode left,TreeNode right){
//当左右节点有一个为空时,返回false,左右节点都为空时,返回true
if(left == null || right == null){
return left == right;
}
//左节点的值不等于右节点的值,返回false
if(left.val != right.val){
return false;
}
//递归比较左节点的左节点和右节点的右节点,左节点的右节点和右节点的左节点
return isMirror(left.left,right.right) && isMirror(left.right,right.left);
}
迭代法:
迭代法我们借助队列这一数据结构来实现
在迭代法中我们是从上到下一次比较左节点的左节点和右节点的右节点,左节点的右节点和右节点的左节点,比较完一对镜面对称的节点之后再将这一对节点的左右节点入队列,注意,入队列的顺序很重要。一定是成镜面对称的节点为一组依次加入,具体实现见下面完整代码。
动态图如下:
public boolean isSymmetric(TreeNode root){
//定义队列
Queue<TreeNode> queue = new LinkedList<TreeNode>();
//将root节点入队列,第一次迭代可以认为root节点既是左节点又是有节点
queue.add(root);
queue.add(root);
//在while循环中迭代判断
while(queue.size() > 1){
//从队列中poll出一对左右节点进行比较
TreeNode left = queue.poll();
TreeNode right = queue.poll();
if(left == null && right == null){
//特别注意,此处不同与递归法,不能直接return true,不然就会直接结束函数,这一对左右节点下面的节点就不会被比较,递归则不会,它会回溯到上一层继续比较
continue;
}
//如果左右节点只有一个为空,就直接返回false,此二叉树不对称
if(left == null || right == null){
return false;
}
//左右节点的值不相等,直接返回false,不对称
if(left.val != right.val){
return false;
}
//比较完之后,再将这一对左右节点的左右节点入队列。注意,入队列的顺序很重要
//left.left和right.right成镜面对称
queue.add(left.left);
queue.add(right.right);
//left.right和right.left成镜面对称
queue.add(left.right);
queue.add(right.left);
}
return true;
}