LeetCode解题笔记:二叉树主题


二叉树,树的每个节点最多只能有两个子节点。

二叉树的操作主要有遍历、查找、删除等等。一棵树要么是空树,要么有两个指针,每个指针指向一棵树。树是一种递归结构,很多树的问题可以使用递归来处理。

LeetCode定义的二叉树结构:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

1. 树的高度

104. Maximum Depth of Binary Tree (Easy)

思路:

利用递归,递归出口是root==null,最终返回左、右子树的最大值+1;

代码:

public int maxDepth(TreeNode root) {
	if (root == null) {
		return 0;
	}

	int l = maxDepth(root.left);
	int r = maxDepth(root.right);
	return Math.max(l, r) + 1;        
}

树的高度

2. 平衡树

110. Balanced Binary Tree (Easy)

Given the following tree [3,9,20,null,null,15,7]:

    3
   / \
  9  20
    /  \
   15   7

思路:

利用求解树的高度的方法,在求高度的同时,判断左右字数的高度是否大于1。

代码:

boolean isBalance = true;
public boolean isBalanced(TreeNode root) {
	getDepth(root);
	return isBalancel;
}

private int getDepth(TreeNode root) {
	if (root == null) {
		return 0;
	}

	int l = getDepth(root.left);
	int r = getDepth(root.right);
  // 大于1,则标志位置为false
	if (Match.abs(l-r) > 1) {
		isBalance = false;
	}

	return Math.max(l, r) + 1;
}

2.1 判断是否是查找二叉树

110. Balanced Binary Tree (Easy)

验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

    节点的左子树只包含小于当前节点的数。
    
    节点的右子树只包含大于当前节点的数。
    
    所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:
    2
   / \
  1   3
输出: true

示例 2:

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
     根节点的值为 5 ,但是其右子节点值为 4 。

思路:

中序遍历展开二叉树,然后判断是否是有序序列。

代码:

private List<Integer> al = new ArrayList<>();

public boolean isValidBST(TreeNode root) {
	inOrder(root);
	for (int i = 0; i < al.size()-1; i++) {
		if (al.get(i) >= al.get(i+1)) {
			return false;
		}
	}

	return true;
}

private void inOrder(TreeNode root) {
	if (root != null) {
		inOrder(root.left);
		al.add(root.val);
		inOrder(root.right);
	}
}

3. 两节点的最长路径

543. Diameter of Binary Tree (Easy)

给定一棵二叉树,你需要计算它的直径长度。

一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。

示例 :
给定二叉树

              1
             / \
            2   3
           / \     
          4   5    

返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

注意:两结点之间的路径长度是以它们之间边的数目表示。

思路:

还是利用树的高度的方法,在求高度的同时,计算l+r的最大值。

代码:

private int max = 0;
public int diameterOfBinaryTree(TreeNode root) {
	getDepth(root);
	return max;        
}

private int getDepth(TreeNode root) {
	if (root == null) {
		return 0;
	}

	int l = getDepth(root.left);
	int r = getDepth(root.right);
	// 左右子树加起来的最大值
	max = Math.max(l+r, max);
	return Math.max(l, r) + 1;
}

4. 翻转树

226. Invert Binary Tree (Easy)

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

思路:

利用递归的原理,交换root的左右子树,交换前要先保存。

代码:

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

翻转二叉树

5. 归并两棵树

617. Merge Two Binary Trees (Easy)

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。

你需要将他们合并为一个新的二叉树。

合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,

否则不为 NULL 的节点将直接作为新二叉树的节点。

Input:
       Tree 1                     Tree 2
          1                         2
         / \                       / \
        3   2                     1   3
       /                           \   \
      5                             4   7

Output:
         3
        / \
       4   5
      / \   \
     5   4   7

思路:

此问题比较简单,直接合并即可

代码:

public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
	if (t1 == null) {
		return t2;
	}

	if (t2 == null) {
		return t1;
	}

	TreeNode root = new TreeNode(t1.val + t2.val);
	root.left = mergeTrees(t1.left, t2.left);
	root.right = mergeTrees(t1.right, t2.right);

	return root;     
}

合并二叉树

6. 判断路径和是否等于一个数

Leetcdoe : 112. Path Sum (Easy)

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,
这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例: 
给定如下二叉树,以及目标和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

思路:

递归处理,每一轮递归都判断当前val与sum是否相等,递归时传入的是sum-root.val

代码:

public boolean hasPathSum(TreeNode root, int sum) {
	if (root == null) {
		return false;
	}

	if (root.left == null && root.right == null && root.val == sum) {
		return true;
	}

	return hasPathSum(root.left, sum - root.val) 
		|| hasPathSum(root.right, sum - root.val);
}

路径总和