层序遍历 226.翻转二叉树 (优先掌握递归) 101. 对称二叉树 (优先掌握递归)
102.二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
思路
迭代法
二叉树的层序遍历
定义队列来保存层序遍历的结果。题目要求,一层的元素要在一个List。但是如何控制弹出的元素是一层的呢?
定义一个size来表示该层的元素数量,元素出队size减一.size ==0 ,那么该层元素都已经出队了,队列中剩下的元素就是下一层的元素,继续循环,最后直到队列为空,中止
代码如下
// 空间复杂度o(n) // 时间复杂度o(n) public List<List<Integer>> levelOrder1(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if (root == null) { return result; } Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { int size = queue.size(); List<Integer> list = new ArrayList<>(); while (size > 0) { TreeNode temp = queue.poll(); list.add(temp.val); if(temp.left != null){ queue.add(temp.left); } if(temp.right != null){ queue.add(temp.right); } size--; } result.add(list); } return result; }
226.翻转二叉树 (优先掌握递归)
翻转一棵二叉树。
这道题目背后有一个让程序员心酸的故事,听说 Homebrew的作者Max Howell,就是因为没在白板上写出翻转二叉树,最后被Google拒绝了。(真假不做判断,权当一个乐子哈)
思路
迭代法
该题的关键在于交换左右子节点,那么只要采用一种遍历方式,在遍历树的同时,会访问当前节点的左右子结点,那么在访问之前交换左右结点即可。
我这里采用的是层序遍历的迭代法,其实递归算法也一样,关键在于交换左右节点即可,熟悉那种写法就写哪种
代码如下
// 空间复杂度o(n)
// 时间复杂度o(n)
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
while (size > 0) {
TreeNode temp = queue.poll();
TreeNode tempLeft = temp.left;
temp.left = temp.right;
temp.right = tempLeft;
if(temp.left != null){
queue.add(temp.left);
}
if(temp.right != null){
queue.add(temp.right);
}
size--;
}
}
return root;
}
101. 对称二叉树 (优先掌握递归)
给定一个二叉树,检查它是否是镜像对称的。
思路
思路:递归法
后序遍历
这道题目,可以采用后序遍历递归的方法,来比较根节点左右子树是否对称
对称二叉树比较的是根节点下两个左右子树是否对称。比如左子树的左节点和右子树的右结点要相同
那么为什么要使用后序遍历?前序和中序不可以吗?
首先后序遍历应用的场景是,父节点需要知道左右子树结点的信息。像该题,根节点需要知道左右子树的信息才可以判断是否对称
递归法三要素
方法的返回值和入参 boolean Treenode leftNode TreeNode rightNode
方法的终止条件 1.如果两节点一个为空,一个不为空,返回false2.两节点都为空 返回true 3.两节点都不为空,值不相等,返回false 4.两节点值相等
方法的核心逻辑 左子树的左节点和右子树的右节点是否相等 左子树的右节点和右子树的左节点是否相等
其实单单是文字描述,可能理解的不透彻,下面给出前序遍历的递归法和后序遍历递归法代码,比较一下,细细品味
前序遍历 左右子树都没有处理,上来就像得到结果,根本行不通
// 前序遍历
public boolean compare(TreeNode leftNode, TreeNode rightNode) {
if (leftNode == null && rightNode != null) {
return false;
} else if (leftNode != null && rightNode == null) {
return false;
} else if (leftNode == null && rightNode == null) {
return true;
} else if (leftNode.val != rightNode.val) {
return false;
}
Boolean result = result1&&result2;
Boolean result1 = true;
Boolean result2 = true;
result1 = compare(leftNode.left, rightNode.right);
result2 = compare(leftNode.right, rightNode.left);
return result;
}
后序遍历代码如下
// 空间复杂度o(n)
// 时间复杂度o(n)
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return compare(root.left, root.right);
}
public boolean compare(TreeNode leftNode, TreeNode rightNode) {
if (leftNode == null && rightNode != null) {
return false;
} else if (leftNode != null && rightNode == null) {
return false;
} else if (leftNode == null && rightNode == null) {
return true;
} else if (leftNode.val != rightNode.val) {
return false;
}
Boolean result1 = compare(leftNode.left, rightNode.right);
Boolean result2 = compare(leftNode.right, rightNode.left);
return result1 && result2;
}