剑指 Offer 55 - II. 平衡二叉树
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true 。
示例 2:
给定二叉树 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false 。
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
//对于当前遍历到的节点,首先计算左右子树的高度,如果左右子树的高度差是否不超过 1,再分别递归地遍历左右子节点,并判断左子树和右子树是否平衡。
//递归
if(root==null){
return true;
}
if(root.left==null && root.right==null){
return true;
}
return Math.abs(depth(root.left)-depth(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
}
//用于计算二叉树中的任意一个节点node的高度
public int depth(TreeNode node){
if(node == null){
return 0;
}
int Left=depth(node.left);
int Right=depth(node.right);
return Math.max(Left,Right)+1;
}
}
结果:
执行用时:1 ms, 在所有 Java 提交中击败了71.73%的用户
内存消耗:38.5 MB, 在所有 Java 提交中击败了48.11%的用户
通过测试用例:227 / 227
剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5
/ \
2 6
/ \
1 3
示例 1:
输入: [1,6,3,2,5]
输出: false
示例 2:
输入: [1,3,2,6,5]
输出: true
解析过程:
class Solution {
/*
后序遍历定义: 左子树 右子树 根节点,即遍历顺序为 左、右、根
二叉搜索树定义: 左子树中所有节点的值 < 根节点的值;右子树中所有节点的值 > 根节点的值;其左、右子树也分别为二叉搜索树
*/
public boolean verifyPostorder(int[] postorder) {
return verify(postorder,0,postorder.length-1);
}
public boolean verify(int[] postorder,int L,int R){
//终止条件: 当L >= R ,说明此子树节点数量≤1 ,无需判别正确性,因此直接返回 true;
if(L >= R){
return true;
}
/*
1.最后一个节点为根节点,要先通过找到第一个大于根节点的节点,划分左右子树,索引记为value.
2.判断是否为二叉搜索树:
1)左子树区间 [L,value - 1]内的所有节点都应< postorder[R]。而第 1.划分左右子树 步骤已经保证左子树区间的正确性,因此只需要判断右子树区间即可。
2)右子树区间 [value, R-1]内的所有节点都应> postorder[R]。实现方式为遍历,当遇到≤postorder[R] 的节点则跳出;则可通过index==R判断是否为二叉搜索树。
3.递归
*/
int index=L;
while(postorder[index]<postorder[R]){
index++;
}
int value=index;
while(postorder[index]>postorder[R]){
index++;
}
//所有子树都需正确才可判定正确
return index==R && verify(postorder,L,value-1) && verify(postorder,value,R-1);
}
}
结果:
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36 MB, 在所有 Java 提交中击败了30.48%的用户
通过测试用例:23 / 23
剑指 Offer 32 - I. 从上到下打印二叉树
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回:
[3,9,20,15,7]
提示:节点总数 <= 1000
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//因为最后是以数组的形式输出,但是数组不能直接添加元素,所以需要一个可以改变大小的数组为ArrayList
//若要从上到下,从左到右打印二叉树的每个节点,需要采用层次遍历
public int[] levelOrder(TreeNode root) {
List<Integer> list=new ArrayList<>();
if(root==null){
return new int[0];
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(! queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode cur=queue.poll();
list.add(cur.val);
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
}
int[] res=new int[list.size()];
for(int i=0;i<list.size();i++){
res[i]=list.get(i);
}
return res;
}
}
结果:
执行用时:1 ms, 在所有 Java 提交中击败了98.13%的用户
内存消耗:38.5 MB, 在所有 Java 提交中击败了59.80%的用户
通过测试用例:34 / 34
剑指 Offer 32 - II. 从上到下打印二叉树 II
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
提示:节点总数 <= 1000
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
//采用层次遍历
List<List<Integer>> list=new ArrayList<>();
if(root == null){
return list;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
List<Integer> level=new ArrayList<>();
for(int i=0;i<size;i++){
TreeNode cur=queue.poll();
level.add(cur.val);
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
list.add(level);
}
return list;
}
}
结果:
执行用时:1 ms, 在所有 Java 提交中击败了93.59%的用户
内存消耗:38.6 MB, 在所有 Java 提交中击败了53.08%的用户
通过测试用例:34 / 34
剑指 Offer 32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[20,9],
[15,7]
]
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
//层序遍历
//此处需要一个双端队列,对当前层节点的存储需要设置一个flag记录是从左至右还是从右至左的
//从左至右:将遍历到的节点插入双端队列的末尾 offerLast()方法用于在此双端队列的最后添加给定元素
//从右至左:将遍历到的节点插入双端队列的头部 offerFirst()方法用于将给定元素添加到此双端队列的前面
List<List<Integer>> list=new ArrayList<>();
if(root==null){
return list;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
boolean flag=true;
while(!queue.isEmpty()){
int size=queue.size();
Deque<Integer> DQ=new ArrayDeque<>();
for(int i=0;i<size;i++){
TreeNode cur=queue.poll();
if(flag){
DQ.offerLast(cur.val);
}else{
DQ.offerFirst(cur.val);
}
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
list.add(new ArrayList<Integer>(DQ));
flag=!flag;
}
return list;
}
}
结果:
执行用时:2 ms, 在所有 Java 提交中击败了7.59%的用户
内存消耗:38.4 MB, 在所有 Java 提交中击败了81.77%的用户
通过测试用例:34 / 34
剑指 Offer 27. 二叉树的镜像
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
示例 1:
4
/ \
2 7
/ \ / \
1 3 6 9
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
4
/ \
7 2
/ \ / \
9 6 3 1
限制:
0 <= 节点个数 <= 1000
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
//递归 从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转得到镜像。将每个节点的左右子树进行交换
public TreeNode mirrorTree(TreeNode root) {
if(root == null){
return null;
}
DFS(root);
return root;
}
public TreeNode DFS(TreeNode node){
if(node == null){
return null;
}
TreeNode Temp1=DFS(node.left);
TreeNode Temp2=DFS(node.right);
node.left=Temp2;
node.right=Temp1;
return node;
}
}
结果:
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:35.7 MB, 在所有 Java 提交中击败了66.03%的用户
通过测试用例:68 / 68
方法二:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode invertTree(TreeNode root) {
//递归,先交换一下左右节点,然后再递归的交换左节点,右节点
//递归函数的终止条件,节点为空时返回
if(root == null){
return null;
}
//当前节点的左右子树进行交换
TreeNode temp=null;
temp=root.left;
root.left=root.right;
root.right=temp;
//递归
TreeNode left=invertTree(root.left);
TreeNode right=invertTree(root.right);
return root;
}
}