二叉树的涉及的题

二叉树的定义

1
2
3
4
5
6
7
8
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}

1.二叉树的最大深度

https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

1
2
3
4
5
6
7
8
9
   public int maxDepth(TreeNode root) {  
if(root!=null){
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left,right)+1;
}else{
return 0;
}
}

2.二叉树的最小深度

https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static int minDepth(TreeNode root) {
if(root == null) {
return 0;
}
if ((root.left == null) && (root.right == null)) {
return 1;
}
int minDepth = Integer.MAX_VALUE;
if(root.left != null) {
minDepth = Math.min(minDepth, minDepth(root.left));
}

if(root.right != null) {
minDepth = Math.min(minDepth, minDepth(root.right));
}

return minDepth + 1;
}
}

3..求完全二叉树中节点的个数

https://leetcode-cn.com/problems/count-complete-tree-nodes/

1
2
3
4
5
6
7
8
9
public int countNodes(TreeNode root) {
if(root==null){
return 0;
}
int left = countNodes(root.left);
int right = countNodes(root.right);
return left+right +1;

}

4. 平衡二叉树

https://leetcode-cn.com/problems/balanced-binary-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null)
return true;
if(Math.abs(getDepth(root.left)-getDepth(root.right))<=1){
return isBalanced(root.left) &&isBalanced(root.right);
}else{
return false;
}
}
//树的深度
public int getDepth(TreeNode root){
if(root == null)
return 0;
int left = getDepth(root.left);
int right = getDepth(root.right);
return Math.max(left,right)+1;
}
}

5.二叉树的完全性检验

https://leetcode-cn.com/problems/check-completeness-of-a-binary-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public boolean isCompleteTree(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
//加入根节点
queue.add(root);
boolean hasNoChild = false;
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (hasNoChild) {
//上一层中左子树不为空,右子树为空,如果遍历到左子树,这时候左子树有孩子,则代表上一层不完全填满
if(node.left!=null || node.right!=null){
return false;
}
} else {
if (node.left != null && node.right != null) { //左右子树不为空
queue.add(node.left);
queue.add(node.right);
} else if (node.left != null && node.right == null) { //左子树不为空,右子树为空
queue.add(node.left);
hasNoChild = true;
} else if (node.left == null && node.right != null) {//左子树为空,右子树不为空
return false;
} else { //左右子树都为空
hasNoChild = true;
}
}
}
return true;
}
}

6.相同的树

https://leetcode-cn.com/problems/same-tree/

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q==null)
return true;
if(p==null ||q == null)
return false;
if(p.val !=q.val)
return false;
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
}

7.对称二叉树

https://leetcode-cn.com/problems/symmetric-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public static boolean isSymmetric(TreeNode root) {
if(root == null)
return true;
return Symmetric(root.left,root.right);
}
public static boolean Symmetric(TreeNode leftroot,TreeNode rightroot) {
if(leftroot==null && rightroot==null)
return true;
if(leftroot==null || rightroot == null)
return false;
if(leftroot.val != rightroot.val)
return false;
return Symmetric(leftroot.left,rightroot.right) && Symmetric(leftroot.right,rightroot.left);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public static boolean isSymmetric(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
queue.add(root);
while(!queue.isEmpty()){
TreeNode node1 = queue.poll();
TreeNode node2 = queue.poll();

if(node1==null && node2==null)
continue;
if(node1==null || node2==null)
return false;
if(node1.val!=node2.val)
return false;
queue.add(node1.left);
queue.add(node2.right);
queue.add(node1.right);
queue.add(node2.left);
}
return true;
}
}

8.翻转二叉树

https://leetcode-cn.com/problems/invert-binary-tree/

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {

public TreeNode invertTree(TreeNode root) {
if(root == null)
return null;
TreeNode right = invertTree(root.right);
TreeNode left = invertTree(root.left);
root.left = right;
root.right = left;
return root;
}
}

9.二叉搜索树的最近公共祖先

https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//都在右子树
if(p.val >root.val && q.val >root.val){
return lowestCommonAncestor(root.right,p,q);
}else if(p.val<root.val && q.val <root.val){ //都在左子树
return lowestCommonAncestor(root.left,p,q);
}else{ //一个在左子树,一个在右子树
return root;
}
}
}

10.二叉树的最近公共祖先

https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

1
2
3
4
5
6
7
8
9
class Solution {
TreeNode lowestCommonAncestor(TreeNode root,TreeNode p,TreeNode q){
if(root==null || root==p || root == q)
return root;
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
return left==null ? right : right == null?left:root;
}
}

11.最深叶节点的最近公共祖先

https://leetcode-cn.com/problems/lowest-common-ancestor-of-deepest-leaves/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public TreeNode lcaDeepestLeaves(TreeNode root) {
if (root == null){
return null;
}
//左子树的深度
int left = depth(root.left);
int right = depth(root.right);
//如果左右子树深度相同,表示获取到了最深叶子节点的最近公共祖先
if (left == right){
return root;
//如果左右子树不等高,高度小的那个子树节点的叶子节点的深度肯定不是最深的(因为比高度大的子树深度小)。
//所以,最深叶子节点肯定在深度较大的子树当中,采用深度优先搜索,每次只要继续往深度更大的子树进行递归即可。
}else if(left > right){
return lcaDeepestLeaves(root.left);
}else {
return lcaDeepestLeaves(root.right);
}
}
//求二叉树的深度
private int depth(TreeNode root){
if (root == null){
return 0;
}
int left = depth(root.left);
int right = depth(root.right);
return 1 + Math.max(left,right);
}
}

12.节点与其祖先中间的最大差值

https://leetcode-cn.com/problems/maximum-difference-between-node-and-ancestor/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {

public static int maxAncestorDiff(TreeNode root) {
if(root == null)
return 0;
return AncestorDiff(root,root.val,root.val);

}
// 每条从根节点到叶子节点的路径中的最大值和最小值,并求出差值更新全局变量
//一口气遍历到叶子节点,遍历的时候动态保存当前路径的最大节点值和最小节点值
//每当遍历一次叶子节点,将保存好的最大值与最小值之间的差与全局变量 maxvalue 比较,并且取较大值
private static int AncestorDiff(TreeNode root, int max_value, int min_value) {
if(root == null)
return max_value-min_value;
max_value = root.val > max_value ? root.val : max_value;
min_value = root.val < min_value ? root.val : min_value;
return Math.max(AncestorDiff(root.left,max_value,min_value),AncestorDiff(root.right,max_value,min_value));
}

}

13.从前序与中序遍历序列构造二叉树

https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0 || inorder.length == 0)
return null;
//前序的第一个数即为树的根结点
TreeNode root = new TreeNode(preorder[0]);
for(int i = 0;i<inorder.length;i++){
//找到中序中的根节点
if(preorder[0] == inorder[i]){
//pre[1,i+1] 和in[0,i]构成左子树的遍历
root.left = buildTree(Arrays.copyOfRange(preorder,1,i+1),Arrays.copyOfRange(inorder,0,i));
//pre[i+1,len-1]和in[i+1,len-1]构成右子树的遍历
root.right = buildTree(Arrays.copyOfRange(preorder,i+1,preorder.length),Arrays.copyOfRange(inorder,i+1,inorder.length));
break;
}
}
return root;
}
}

14.从中序与后序遍历序列构造二叉树

https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public static TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder.length == 0||postorder.length == 0)
return null;
//后序的最后一个为根结点
TreeNode root = new TreeNode(postorder[postorder.length-1]);
for(int i = 0;i<inorder.length;i++){
//找到中序中的根节点位置
if(inorder[i] == postorder[postorder.length-1]){
//in[0,i]和pos[0,i-1]构成左子树的遍历
root.left = buildTree(Arrays.copyOfRange(inorder,0,i),Arrays.copyOfRange(postorder,0,i));
//in[i+1,len-1]和pos[i,len-2]构成左子树的遍历
root.right = buildTree(Arrays.copyOfRange(inorder,i+1,inorder.length),Arrays.copyOfRange(postorder,i,postorder.length-1));
break;
}
}
return root;
}
}

15.把二叉树转换成累加树

https://leetcode-cn.com/problems/convert-bst-to-greater-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//中序遍历结果为从小到大,要变成累加树,则中序遍历反过来相加变成节点值即可。
class Solution {
int num = 0;
public TreeNode convertBST(TreeNode root) {
if(root!=null){
//遍历右子树
convertBST(root.right);
//改变值,依次累加即可
root.val = root.val+num;
//存储上一层的值
num = root.val;
//遍历左子树
convertBST(root.left);
}
return root;
}
}

16.不同的二叉搜索树

https://leetcode-cn.com/problems/unique-binary-search-trees/

给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?
动态规划

  • 初始化

    假设n个节点存在二叉搜索树的个数是dp(n),令f(i) 为以i为根的二叉搜索树的个数,则有

               dp(n) = f(1) + f(2) + f(3) +... + f(n)

    当i为根节点时,其左子树的个数为(i - 1),右子树的个数为(n-i),则

               f(i) = dp(i-1) *dp(n-i)

    结合两个式子可以得到卡特兰数:

               dp(n) = dp(0) *dp(n-1) +dp(1) *dp(n-2) +... +dp(n-1)*dp(0)

                    = dp(n-1) * C(2n,n)

                    = dp(n-1) * (4*n-2)/(n-1)

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public static int numTrees(int n) {
//n个节点存在二叉树的个数
long []dp = new long[n+1];
//以i为根节点的二叉树个数
dp[0] = 1; //以0为根节点的
dp[1] = 1;
for(int i = 1;i<=n;i++){
dp[i] = dp[i-1]*(4*i-2)/(i+1);
}
return (int) dp[n];
}
}

17.不同的二叉搜索树 II

https://leetcode-cn.com/problems/unique-binary-search-trees-ii/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public List<TreeNode> generateTrees(int n) {
if(n<=0)
return new ArrayList<TreeNode>();
return generate(1,n);
}
public List<TreeNode> generate(int start,int end){
List<TreeNode> res=new ArrayList<>();
if(start>end){
res.add(null);
return res;
}
for(int i=start;i<=end;i++){
// 递归遍历左子树
List<TreeNode> leftTrees=generate(start,i-1);
// 递归遍历右子树
List<TreeNode> rightTrees=generate(i+1,end);
//先序遍历存入以i为根节点的二叉搜索树
for(TreeNode left:leftTrees){
for(TreeNode right:rightTrees){
TreeNode root=new TreeNode(i);
root.left=left;
root.right=right;
res.add(root);
}
}
}
return res;
}
}

18.在二叉树中增加一行

https://leetcode-cn.com/problems/add-one-row-to-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public static TreeNode addOneRow(TreeNode root, int v, int d) {
TreeNode node = new TreeNode(v);
//如果 d 的值为 1,深度 d - 1 不存在,则创建一个新的根节点 v,原先的整棵树将作为 v 的左子树。
if(d == 1){
node.left = root;
return node;
}
if(d == 0){
node.right = root;
return node;
}
if(root != null && d>1){
root.left = addOneRow(root.left ,v, d > 2 ? d - 1 : 1);
root.right = addOneRow(root.right,v, d > 2 ? d - 1 : 0);
}
return root;
}
}

19.验证一棵树是不是二叉搜索树

https://leetcode-cn.com/problems/validate-binary-search-tree/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//根据二叉搜索树的中序遍历为从小到大的思路写的
//修改一下二叉搜索树的非递归写法
class Solution {
public boolean isValidBST(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
double inorder = - Double.MAX_VALUE;
while(!stack.isEmpty() || root != null){
while (root!=null){
stack.push(root);
root = root.left;
}
root = stack.pop();
if(root.val <= inorder){
return false;
}
inorder = root.val;
root = root.right;
}
return true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
if (!isValidBST(root.left)) {
return false;
}
if (pre != null && pre.val >= root.val) {
return false;
}
pre = root;
return isValidBST(root.right);
}
}
文章目录
  1. 1. 二叉树的定义
  • 1.二叉树的最大深度
  • 2.二叉树的最小深度
  • 3..求完全二叉树中节点的个数
  • 4. 平衡二叉树
  • 5.二叉树的完全性检验
  • 6.相同的树
  • 7.对称二叉树
  • 8.翻转二叉树
    1. 1. 9.二叉搜索树的最近公共祖先
  • 10.二叉树的最近公共祖先
  • 11.最深叶节点的最近公共祖先
  • 12.节点与其祖先中间的最大差值
  • 13.从前序与中序遍历序列构造二叉树
  • 14.从中序与后序遍历序列构造二叉树
  • 15.把二叉树转换成累加树
  • 16.不同的二叉搜索树
  • 17.不同的二叉搜索树 II
  • 18.在二叉树中增加一行
  • 19.验证一棵树是不是二叉搜索树
  • | 139.6k