算法训练营 day15 二叉树 层序遍历 翻转二叉树 对称二叉树
层序遍历
102. 二叉树的层序遍历 - 力扣(LeetCode)
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Queue<TreeNode> que = new LinkedList<TreeNode>();
TreeNode node;
if (root!=null) que.offer(root);
while (!que.isEmpty()){
int size = que.size();
List<Integer> flag = new ArrayList<>();
while (size-->0){
node = que.poll();
flag.add(node.val);
if (node.left!=null)que.offer(node.left);
if (node.right!=null)que.offer(node.right);
}
result.add(flag);
}
return result;
}
}
翻转二叉树
226. 翻转二叉树 - 力扣(LeetCode)
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果
递归法
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root==null) return null;
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swap(TreeNode root) {
TreeNode temp;
temp = root.left;
root.left = root.right;
root.right = temp;
}
}
统一迭代法
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root==null) return null;
Stack<TreeNode> st = new Stack<>();
TreeNode node;
if (root!=null) st.push(root);
while (!st.isEmpty()){
node = st.peek();
if (node!=null){
st.pop();
if (node.right!=null)st.push(node.right);
if (node.left!=null)st.push(node.left);
st.push(node);
st.push(null);
}else {
st.pop();
node = st.pop();
swap(node);
}
}
return root;
}
public static void swap(TreeNode root) {
TreeNode temp;
temp = root.left;
root.left = root.right;
root.right = temp;
}
}
层序遍历法
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
Queue<TreeNode> que = new LinkedList<>();
TreeNode node;
if (root != null) que.add(root);
while (!que.isEmpty()) {
int size = que.size();
while (size-- > 0) {
node = que.poll();
swap(node);
if (node.left != null) que.add(node.left);
if (node.right != null) que.add(node.right);
}
}
return root;
}
public static void swap(TreeNode root) {
TreeNode temp;
temp = root.left;
root.left = root.right;
root.right = temp;
}
}
对称二叉树
101. 对称二叉树 - 力扣(LeetCode)
给你一个二叉树的根节点 root
, 检查它是否轴对称。
比较的是两个子树的里侧和外侧的元素是否相等。
递归法
正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下我称之为左节点右节点)
- 左节点为空,右节点不为空,不对称,return false
- 左不为空,右为空,不对称 return false
- 左右都为空,对称,返回true
此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:
- 左右都不为空,比较节点数值,不相同就return false
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left, root.right);
}
private static boolean compare(TreeNode left, TreeNode right) {
if (left==null&&right!=null) return false;
else if (left!=null&&right==null) return false;
else if (left==null&&right==null) return true;
else if (left.val!= right.val) return false;
boolean outside = compare(left.left,right.right);
boolean inside = compare(left.right,right.left);
return outside&&inside;
}
}
迭代法
通过队列来判断根节点的左子树和右子树的内侧和外侧是否相等,如动画所示:
class Solution {
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> que = new LinkedList<>();
que.add(root.left);
que.add(root.right);
while (!que.isEmpty()){
TreeNode leftNode = que.poll();// 将左子树头结点加入队列
TreeNode rightNode = que.poll();// 将右子树头结点加入队列
// 左节点为空、右节点为空,此时说明是对称的
if (leftNode == null && rightNode == null) continue;
// 左右一个节点不为空,或者都不为空但数值不相同,返回false
if (leftNode==null||rightNode==null||(leftNode.val!= rightNode.val)){
return false;
}
que.add(leftNode.left);
que.add(rightNode.right);
que.add(leftNode.right);
que.add(rightNode.left);
}
return true;
}
}
lse;
}
que.add(leftNode.left);
que.add(rightNode.right);
que.add(leftNode.right);
que.add(rightNode.left);
}
return true;
}
}