1.层次遍历二叉树
就是用队列嘛,唯一可能有点问题的就是怎么一层一个数组;每次bfs时,记录一下队列中的元素个数,就表示了这一层有几个结点,然后遍历下一层时指定遍历次数达到本层的结点数目即可,如此反复。
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
Deque<TreeNode> q = new LinkedList<>();
if(root == null) return res;
q.offerLast(root);
while(!q.isEmpty()) {
int size = q.size();
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < size; i ++) {
TreeNode curr = q.poll();
if(curr == null) return res;
list.add(curr.val);
if(curr.left != null) q.offerLast(curr.left);
if(curr.right != null) q.offerLast(curr.right);
}
res.add(list);
}
return res;
2.判断是否为对称二叉树
只需要想到判断条件就迎刃而解了,既:
递归解决:
1.null认为是对称
2.左右结点全为null/全不为null且val相等则认为对称
3.(eg:)第二层的第一个2的右子树等于第二层第二个2的左子树且第二层的第一个2的左子树等于第二层第二个2的右子树则认为对称,这是递归解决最重要的一步。
public boolean sovle(TreeNode l, TreeNode r) {
if(l == null && r == null) return true;
if(l == null && r != null || l != null && r == null) return false;
return l.val == r.val && sovle(l.right, r.left) && sovle(l.left, r.right);
}
public boolean isSymmetric (TreeNode root) {
// write code here
if(root == null) return true;
return sovle(root.left, root.right);
}
迭代解决:用层次遍历是可以的,条件为:
1.每层在队列中的数字必须是对称的
2.结点为null,也需要加入队列,因为可能出现队列对称但由于有null而不对称
和上题一样,每层加一个list,对每个结点判断是否为null,如果为null,则加入-1或其他特定值且不加如其子节点(null的子节点),本层遍历完判断一下是否正确,不正确则返回false即可。
public boolean check(List<Integer> list) {
for(int i = 0, j = list.size() - 1; i < j; i ++, j --) {
if(list.get(i) != list.get(j)) return false;
}
return true;
}
public boolean isSymmetric (TreeNode root) {
if(root == null) return true;
Deque<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()) {
int size = q.size();
List<Integer> list = new ArrayList<>();
for(int i = 0; i < size; i ++) {
TreeNode t = q.poll();
if(t == null) list.add(-1);
else {
list.add(t.val);
q.offer(t.left);
q.offer(t.right);
}
}
if(!check(list)) return false;
}
return true;
}
3.判断是否为平衡二叉树
条件是必须每个结点的左右子树高度差小于等于1
可以写一个计算每个结点高度的方法,遍历树,每个结点都判断一下;
这个显然可看出,每个结点都计算了多次高度,故可以这样:就是后续遍历,如果该点是平衡二叉树则返回其高度,否则返回false/一个表示false标志。
自顶向下:
private int getHigh(TreeNode root) {
if(root == null) return 0;
int ll = getHigh(root.left);
int lr = getHigh(root.right);
return Math.max(ll, lr) + 1;
}
public boolean IsBalanced_Solution(TreeNode root) {
if(root == null) return true;
if(Math.abs(getHigh(root.left) - getHigh(root.right)) > 1) return false;
return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
}
自下而上:(就是边求边解出了答案,求的结果是下一步的答案)
public int getHigh(TreeNode root) {
if(root == null) return 0;
int l = getHigh(root.left);
int r = getHigh(root.right);
if(l == -1 || r == -1 || Math.abs(l - r) > 1) return -1;
return Math.max(l, r) + 1;
}
public boolean IsBalanced_Solution(TreeNode root) {
return getHigh(root) >= 0;
}
4.求二叉树两节点的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点(p, q)的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
树的问题基本总能用递归解决,因为树天生就满足递归条件;就是深搜,对于任何一个结点,都有三种情况:
1.p, q分别在它的左右子树
2.p, q在它的左侧
3.p, q在它的右侧
我们规定:如果在找的过程中没有搜到p, q就返回null(这样的话如果某一个结点的左子树返回了null,那么说明其左子树没有p, q),如果找到了p, q就返回本结点(这样的话如果某一个结点的左子树返回了非null,那么说明其左子树有p, q),如果当前结点的右子树有、左子树没有则返回右子树返回的内容,左子树同理。这样的话返回的就是最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(root == p || root == q) return root;
TreeNode l = lowestCommonAncestor(root.left, p, q);
TreeNode r = lowestCommonAncestor(root.right, p, q);
if(l != null && r != null) return root;
else if(l == null) return r;
else return l;
}