LeetCode刷题笔记(2)——Tree篇

LeetCode刷题笔记(2)——Tree篇

接上一篇,本篇主要记录Tree分类下的相关习题。

目录

94. Binary Tree Inorder Traversal
95. Unique Binary Search Trees II
96. Unique Binary Search Trees
100. Same Tree
101. Symmetric Tree
102. Binary Tree Level Order Traversal
103. Binary Tree Zigzag Level Order Traversal
104. Maximum Depth of Binary Tree
105. Construct Binary Tree from Preorder and Inorder Traversal
106. Construct Binary Tree from Inorder and Postorder Traversal
107. Binary Tree Level Order Traversal II
108. Convert Sorted Array to Binary Search
110. Balanced Binary Tree
111. Minimum Depth of Binary Tree
112. Path Sum
113. Path Sum II
144. Binary Tree Preorder Traversal
145. Binary Tree Postorder Traversal
226. Invert Binary Tree
230. Kth Smallest Element in a BST
235. Lowest Common Ancestor of a Binary Search Tree
257. Binary Tree Paths
404. Sum of Left Leaves

94. Binary Tree Inorder Traversal

Given a binary tree, return the inorder traversal of its nodes’ values.

Example:

Input: [1,null,2,3]
在这里插入图片描述
Output: [1,3,2]

分析:本题需要中序遍历二叉树,并将结果返回到List中。有两种方法。
  第一种方法是使用递归的思想,这里需要一个helper函数,可以存储每次递归返回的结果。对于每个非空节点,依次递归遍历它的左孩子、当前节点的值、递归遍历它的右孩子。helper函数其中的一个输入参数为当前的list。
  第二种方法是在栈的帮助下使用迭代,而不利用递归。
   1.令根节点为当前节点t,将当前节点t压栈。
   2.若当前节点t存在左孩子,也将左孩子压栈,并将左孩子置为当前节点t。
   3.循环执行2,直至当前节点无左孩子,当前节点t出栈,并在list中记录当前节点的val值。
   4.若当前节点t存在右孩子,将右孩子压栈,并将右孩子置为当前节点t。否则栈顶元素出栈,该栈顶元素被置为当前节点t。
   5.重复执行2-4,直至栈空为止。

优化的代码如下:

第一种方法:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        helper(root,list);
        return list;
    }
    private void helper(TreeNode root,List<Integer> list){
        if(root != null){
            helper(root.left,list);
            list.add(root.val);
            helper(root.right,list);
        }
    }
}

第二种方法:迭代

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode t = root;
        while(t != null || !stack.isEmpty()){
            while(t != null){
                stack.push(t);
                t = t.left;
            }
            t = stack.pop();
            list.add(t.val);
            t = t.right;
        }       
        return list;
    }
}
95. Unique Binary Search Trees II

Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1 … n.

Example:

Input: 3
Output:
[
 [1,null,3,2],
 [3,2,null,1],
 [3,1,null,null,2],
 [2,1,3],
 [1,null,2,null,3]
]
Explanation:
The above output corresponds to the 5 unique BST’s shown below:
在这里插入图片描述
分析:本题要求将第96题的多种BST输出,可以使用递归的思想。依次将1到n设为根节点,同时借助genTrees函数,递归求解根节点的左孩子genTrees(start,i-1)和根节点的右孩子genTrees(i+1,end)。然后依次创建树,将根节点及其左孩子和右孩子加入树中。本题需重点理解掌握。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<TreeNode> generateTrees(int n) {
        if(n == 0) return new ArrayList();
        return genTrees(1,n);
    }
    private List<TreeNode> genTrees(int start, int end){
        List<TreeNode> list = new ArrayList<>();
        if(start > end){
            list.add(null);
            return list;
        }
        if(start == end){
            list.add(new TreeNode(start));
            return list;
        }
        List<TreeNode> left, right;
        for(int i = start; i <= end; i++){
            left = genTrees(start, i-1);
            right = genTrees(i+1, end);
            for(TreeNode ln : left){
                for(TreeNode rn : right){
                    TreeNode root = new TreeNode(i);
                    root.left = ln;
                    root.right = rn;
                    list.add(root);
                }
            }
        }        
        return list;
    }
}
96. Unique Binary Search Trees

Given n, how many structurally unique BST’s (binary search trees) that store values 1 … n?

Example:

Input: 3
Output: 5
Explanation: Given n = 3, there are a total of 5 unique BST’s:
在这里插入图片描述
分析:本题求解给定节点个数,可能存在多少种不同的二叉排序树。此题代码编写不难,重点在于对过程的分析。这里,使用了动态规划的思想,即利用求过的解来节省时间。下图给出问题具体的分析过程:(以Input=3为例,当1为根节点时,比1小的左孩子节点个数为0,比1大的右孩子节点个数为2,由前面求过的结果知,Input=0则Output=1,Input=2则Output=2,所以以1为根节点有12=2种,同理以2为根节点有11=1种,以3为根节点有21=2种。因此当Input=3时,Output=12+11+21=5种)
在这里插入图片描述
优化的代码如下:

class Solution {
    public int numTrees(int n) {
        int[] nums = new int[n+1];
        nums[0] = 1;
        nums[1] = 1;
        for(int i = 2; i <= n; i++){
            for(int j = 0; j < i; j++){
                nums[i] += nums[j] * nums[i-1-j];
            }
        }      
        return nums[n];
    }
}
100. Same Tree

Given two binary trees, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical and the nodes have the same value.

Example 1:
在这里插入图片描述
Example 2:
在这里插入图片描述
Example 3:
在这里插入图片描述
分析:本题有两种方法,第一种方法是使用递归的思想,如果两个节点都是空节点返回true,如果两个节点中一个为空另一个非空返回false,如果两个节点的val值不等返回false,如果两个节点都非空并且val值相等,递归求解两个节点的左孩子是否相等,两个节点的有孩子是否相等。
   第二种方法是在队列的帮助下使用迭代,而不利用递归。队列中的每两个连续节点应该相等,并且它们的子树也相等。首先将当前两个节点加入到队列,如果当前两节点对象非空并且val值相等,将第一个节点的左孩子、第二个节点的左孩子、第一个节点的右孩子、第二个节点的右孩子依次加入到队列中。循环取队头的两个节点比较,若出现不相等则不是相同的树,返回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 isSameTree(TreeNode p, TreeNode q) {
        if(p == null && q == null) return true;
        if(p == null && q != null || (p != null && q ==null)) return false;
        if(p.val != q.val) return false;
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }
}

第二种方法:迭代

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        Queue<TreeNode> list = new LinkedList<>();
        list.add(p);
        list.add(q);
        while(!list.isEmpty()){
            TreeNode t1 = list.poll();
            TreeNode t2 = list.poll();
            if(t1==null && t2==null) continue;
            if(t1==null && t2!=null || (t1!=null && t2==null)) return false;
            if(t1.val!=t2.val) return false;
            list.add(t1.left);
            list.add(t2.left);
            list.add(t1.right);
            list.add(t2.right);
        }
        return true;
    }
}
101. Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
在这里插入图片描述
But the following [1,2,2,null,3,null,3] is not:
在这里插入图片描述
Note:
Bonus points if you could solve it both recursively and iteratively.

分析:类似于第100题,本题有两种方法。与之不同的是,本题是判断是否为对称树,对称树要求根节点的左孩子p与根节点右孩子q应相等,并且p的左孩子与q的右孩子相等,同时p的右孩子与q的左孩子相等。因此,第一种方法的递归中,最后应递归求解节点的左孩子是否等于另一个节点的右孩子且节点的右孩子是否等于另一个节点的左孩子。第二种方法的迭代中,在往队列中加入元素时,顺序也应相应的改变。应当依次加入第一个节点的左孩子、第二个节点的右孩子、第一个节点的右孩子、第二个节点的左孩子,然后以同样的方法判断队列中相邻的两个节点是否相等。

优化的代码如下:

第一种方法:递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return isMirror(root.left,root.right);
    }
    private boolean isMirror(TreeNode p, TreeNode q){
    	if(p == null && q == null) return true;
        if(p == null && q != null || (p != null && q == null)) return false;
        if(p.val != q.val) return false;
        return isMirror(p.left,q.right) && isMirror(p.right,q.left);
    }
}

第二种方法:迭代

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        Queue <TreeNode> list = new LinkedList<>();
        list.add(root);
        list.add(root);
        while(!list.isEmpty()){
            TreeNode t1 = list.poll();
            TreeNode t2 = list.poll();
            if(t1==null && t2==null) continue;        
            if(t1==null && t2!=null || (t1!=null && t2==null)) return false;
            if(t1.val != t2.val) return false;
            list.add(t1.left);
            list.add(t2.right);
            list.add(t1.right);
            list.add(t2.left);
        }
        return true;
    }
}
102. Binary Tree Level Order Traversal

Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).

For example:
Given binary tree [3,9,20,null,null,15,7],
在这里插入图片描述
return its level order traversal as:
在这里插入图片描述
分析:本题要求按层次遍历二叉树,有两种方法。
   第一种方法是广度优先搜索遍历BFS。此方法比较易于理解。首先,创建一个队列q,将根节点加入到队列中。1.创建一个链表list存储本层的节点值,并计算当前队列q中的元素个数size。2.取当前队列的队头节点t,将此节点的值val加入到链表list中。如果节点t存在左孩子,将其左孩子加入到队列q中;如果节点t存在右孩子,将其右孩子加入到队列q中。3.重复执行过程2 size次,然后将list加入到结果链表lists中。4.重复过程1-3直至队列q空为止。
   第二种方法是利用递归。递归的方法中借助了一个helper函数,函数的输入参数有存储结果的链表lists、节点root和当前节点的层数height。在helper函数中,如果节点root为空就返回。如果lists中未包含当前层的val信息,就在lists中创建一个元素,并将root的val加入其中。然后递归该root节点的左孩子,递归当前节点的右孩子,注意其孩子节点的层数为height+1。

优化的代码如下:

第一种方法:广度优先搜索遍历BFS

/**
 * 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) {
        if(root == null) return new ArrayList();
        List<List<Integer>> lists = new ArrayList<>();
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
            List<Integer> list = new ArrayList<>();
            int size = q.size();
            for(int i = 0; i < size; i++){
                TreeNode t = q.poll();
                list.add(t.val);
                if(t.left != null)
                    q.add(t.left);
                if(t.right != null)
                    q.add(t.right);
            }
            lists.add(list);
        }    
        return lists;
    }
}

第二种方法:递归

/**
 * 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>> lists = new ArrayList<>();
        helper(lists, root, 0);
        return lists;
    }
    private void helper(List<List<Integer>> lists, TreeNode root, int height){
        if(root == null) return;
        if(lists.size() <= height){
            lists.add(new ArrayList());
        }
        lists.get(height).add(root.val);
        helper(lists,root.left,height+1);
        helper(lists,root.right,height+1);
    }
}
103. Binary Tree Zigzag Level Order Traversal

Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],
在这里插入图片描述
return its zigzag level order traversal as:
在这里插入图片描述
分析:本题承接第102题,不同的是输出内容将偶数层的元素内容反转。因此只需要在将list加入结果链表lists之前,判断一下当前是否为偶数层,如果是,就反转list后再加入到结果中。

优化的代码如下:

/**
 * 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>> zigzagLevelOrder(TreeNode root) {
        if(root == null)
            return new ArrayList();
        List<List<Integer>> lists = new ArrayList<>();
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        int count = 0;
        while(!q.isEmpty()){
            List<Integer> list = new ArrayList<>();
            int size = q.size();
            count++;
            for(int i = 0; i < size; i++){
                TreeNode t = q.poll();
                list.add(t.val);
                if(t.left != null)
                    q.add(t.left);
                if(t.right != null)
                    q.add(t.right);
            }
            if(count % 2 == 0)
                Collections.reverse(list);
            lists.add(list);
        }
        return lists;
    }
}
104. Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

Note: A leaf is a node with no children.

Example:

Given binary tree [3,9,20,null,null,15,7],
在这里插入图片描述
return its depth = 3.

分析:本题求解树的高度,使用递归的方法。当根节点为空时,返回0。否则递归求解左子树的深度与右子树深度的最大值,最大值加1即为该树的高度。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }else{
            return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
        }            
    }
}
105. Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.

Example:

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
在这里插入图片描述
分析:本题给定前序遍历preorder和中序遍历inorder的序列,要求输出二叉树。
   我的思路是将preorder中的第一个元素作为root,然后在inorder中查找root,并记录下标index。那么inorder中index左侧的元素即为root的左子树,index右侧的元素即为root的右子树。这里我采用的方法是创建了四个新的数组,然后递归调用buildTree函数生成左子树和右子树,最终返回root。由于过程中反复创建新数组,导致算法的复杂度较高,因此我学习了更优化的方法。
   学习到的方法是借助了helper函数,将记录左右子树范围的指针preStart,inStart,inEnd作为函数的输入参数。preStart指向preorder中的root,inStart和inEnd分别指向在inorder中左子树或右子树的范围。这样的做法避免了反复创建新数组的操作,大大提高了算法的执行效率。总体流程与方法一类似,难点在于递归调用helper函数生成左右子树时,指针位置更新的计算。这里解释一下右子树的preStart的计算:preStart+1+index-inStart。preStart+1表示对应的左子树的起始位置(即左子树的根节点),index-inStart表示左子树包含的节点个数,因此将二者相加即求得了右子树的起始位置(即右子树的根节点)。
在这里插入图片描述

在这里插入图片描述

优化的代码如下:

我的思路:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length == 0 || inorder.length == 0) return null;
        TreeNode root = new TreeNode(preorder[0]);
        int index = -1;     //记录当前节点在中序遍历数组中的下标
        for(int i = 0; i < inorder.length; i++){
            if(inorder[i] == root.val){
                index = i;
                break;
            }
        }
        int[] subleftpre = Arrays.copyOfRange(preorder, 1, index+1);
        int[] subrightpre = Arrays.copyOfRange(preorder, index+1, preorder.length);
        int[] subleftin = Arrays.copyOfRange(inorder, 0, index);
        int[] subrightin = Arrays.copyOfRange(inorder, index+1, inorder.length);
        root.left = buildTree(subleftpre,subleftin);
        root.right = buildTree(subrightpre,subrightin);
        return root;
    }
}

学习到的方法:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return helper(0, 0, preorder.length-1, preorder, inorder);
    }
    private TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder){
        if(preStart > preorder.length - 1 || inStart > inEnd) return null;
        TreeNode root = new TreeNode(preorder[preStart]);
        int index = -1;
        for(int i = inStart; i <= inEnd; i++){
            if(inorder[i] == root.val){
                index = i;
                break;
            }
        }
        root.left = helper(preStart+1, inStart, index-1, preorder, inorder);
        root.right = helper(preStart+1+index-inStart, index+1, inEnd, preorder, inorder);
        return root;
    }
}
106. Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.
Note: You may assume that duplicates do not exist in the tree.

Example:

inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
在这里插入图片描述
分析:本题与第105题解法类似。同样问题的难点在于递归调用helper函数生成左右子树时,指针位置更新的计算。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return helper(postorder.length-1, 0, inorder.length-1, inorder, postorder);
    }
    private TreeNode helper(int postStart, int inStart, int inEnd, int[] inorder,int[] postorder){
        if(postStart < 0 || inStart > inEnd) return null;
        TreeNode root = new TreeNode(postorder[postStart]);
        int index = -1;
        for(int i = inStart; i <= inEnd; i++){
            if(inorder[i] == root.val){
                index = i;
                break;
            }
        }
        root.left = helper(postStart-1-(inEnd-index), inStart, index-1,inorder, postorder);
        root.right = helper(postStart-1, index+1, inEnd, inorder, postorder);
        return root;
    }
}
107. Binary Tree Level Order Traversal II

Given a binary tree, return the bottom-up level order traversal of its nodes’ values. (ie, from left to right, level by level from leaf to root).

For example:
Given binary tree [3,9,20,null,null,15,7],
在这里插入图片描述
return its bottom-up level order traversal as:
在这里插入图片描述
分析:本题承接第102题,不同的是将结果链表lists中的元素反转即可,基于第102题,此题没有难度。

优化的代码如下:

/**
 * 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>> levelOrderBottom(TreeNode root) {
        if(root == null) return new ArrayList<>();
        List<List<Integer>> lists = new ArrayList<>();
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
            ArrayList<Integer> list = new ArrayList<>();
            int size = q.size();
            for(int i = 0; i < size; i++){
                TreeNode t = q.poll();
                list.add(t.val);
                if(t.left != null)
                    q.add(t.left);
                if(t.right != null)
                    q.add(t.right);
            }
            lists.add(list);
        }
        Collections.reverse(lists);
        return lists;
    }
}
108. Convert Sorted Array to Binary Search

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example:

Given the sorted array: [-10,-3,0,5,9],
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
在这里插入图片描述
分析:本题适合使用递归的思想进行求,需要借助一个helper函数,将有序数组、最低位以及最高位作为函数的参数。其中将数组的中间值加入到树节点中,并递归形成它的左孩子和右孩子。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        if(nums.length == 0) return null;
        TreeNode t = helper(nums, 0, nums.length-1);
        return t;
    }
    private TreeNode helper(int[] nums, int low, int high){
        if(low > high) return null;
        int mid = (low + high) / 2;
        TreeNode t = new TreeNode(nums[mid]);
        t.left = helper(nums, low, mid-1);
        t.right = helper(nums, mid+1, high);
        return t;
    }
}
110. Balanced Binary Tree

Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example 1:

Given the following tree [3,9,20,null,null,15,7]:
在这里插入图片描述
Return true.

Example 2:

Given the following tree [1,2,2,3,3,null,null,4,4]:
在这里插入图片描述
Return false.

分析:本题求解输入的是否为平衡二叉树,即树的每个节点的左右孩子高度差值是否不超过1。这里,我的思路是借助一个递归函数depth求得节点的高度,然后利用队列q存储每个节点,依次验证每个节点是否符合平衡二叉树的要求。

优化的代码如下:

/**
 * 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) {
        if(root == null) return true;
        Queue<TreeNode> q = new LinkedList<>();
        q.add(root);
        TreeNode t;
        while(!q.isEmpty()){
            t = q.poll();
            if(Math.abs(depth(t.left) - depth(t.right)) > 1)
                return false;
            if(t.left != null)
                q.add(t.left);
            if(t.right != null)
                q.add(t.right);
        }
        return true;
    }
    private int depth(TreeNode t){
        if(t == null) return 0;
        return Math.max(depth(t.left),depth(t.right))+1;
    }
}
111. Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
Note: A leaf is a node with no children.

Example:

Given binary tree [3,9,20,null,null,15,7],
在这里插入图片描述
return its minimum depth = 2.

分析:本题求解最小深度,也可以使用递归的思想解决。但是注意对特殊节点的处理,对于只有左孩子或只有右孩子的节点,应继续向下寻找叶子节点。因此我的思路是借助helper函数将节点为空的情况返回最大整数,使取最小值的时候取不到。或者采用刚学到的方法:若节点只有左孩子或只有右孩子,返回二者结果的和再加1,其他情况返回二者结果中最小值加1。

优化的代码如下:

我的思路:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        return helper(root);
    }
    private int helper(TreeNode root){
        if(root == null) return Integer.MAX_VALUE;
        if(root.left == null && root.right == null) return 1;        
        return Math.min(helper(root.left), helper(root.right))+1;
    }
}

学习到的方法:

public class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        int left = minDepth(root.left);
        int right = minDepth(root.right);
        return (left == 0 || right == 0) ? left + right + 1: Math.min(left,right) + 1;
       
    }
}
112. Path Sum

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
Note: A leaf is a node with no children.

Example:

Given the below binary tree and sum = 22,
在这里插入图片描述
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

分析:本题适合使用递归的思想解决。当节点为叶子节点且节点的值恰好等于sum时,返回true。否则,递归求解其左孩子或右孩子中是否存在路径的和为sum-root.val。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    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);
    }
}
113. Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
Note: A leaf is a node with no children.

Example:

Given the below binary tree and sum = 22,
在这里插入图片描述
Return:
[
 [5,4,11,2],
 [5,8,4,5]
]

分析:承接第112题,本题可以使用递归的方法,这里需要借助dfs函数,将root、sum、allPaths和path作为函数的输入参数。在递归的方法中,最重要的是path.remove(path.size() - 1); 目的是回溯到上一个递归层以便递归遍历其他分支。除了递归的方法外,本题还可以利用栈进行迭代的方法,此方法需要清楚地理解进栈出栈的过程。

优化的代码如下:

第一种方法:递归

/**
 * 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>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> allPaths = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        dfs(root, sum, allPaths, path);
        return allPaths;
    }
    private void dfs(TreeNode root, int sum, List<List<Integer>> allPaths, List<Integer> path){
        if(root == null) return;
        path.add(root.val);
        if(root.left == null && root.right == null && root.val == sum){
            allPaths.add(new ArrayList(path));
        }else{
            dfs(root.left, sum-root.val, allPaths,path);
            dfs(root.right, sum-root.val, allPaths, path);
        }
        path.remove(path.size() - 1);
    }
}

第二种方法:迭代,借助stack

/**
 * 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>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> allPaths = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        int SUM = 0;
        TreeNode cur = root;
        TreeNode pre = null;
        while(cur!=null || !stack.isEmpty()){
            while(cur!=null){
                stack.push(cur);
                path.add(cur.val);
                SUM+=cur.val;
                cur=cur.left;
            }
            cur = stack.peek();
            if(cur.right!=null && cur.right!=pre){
                cur = cur.right;
                continue;
            } 
            if(cur.left==null && cur.right==null && SUM==sum) 
                allPaths.add(new ArrayList<Integer>(path)); 
            pre = cur;
            stack.pop();
            path.remove(path.size()-1);
            SUM-=cur.val;
            cur = null;      
        }
        return allPaths;
    }
}
144. Binary Tree Preorder Traversal

Given a binary tree, return the preorder traversal of its nodes’ values.

Example:

Input: [1,null,2,3]
在这里插入图片描述
Output: [1,2,3]

分析:本题要求前序遍历二叉树,属于基本题,用递归的方法实现即可。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root == null) return new ArrayList<>();
        List<Integer> result = new ArrayList<>();
        helper(root,result);
        return result;
    }
    private void helper(TreeNode root, List<Integer> result){
        if(root == null) return null;
        result.add(root.val);
        helper(root.left,result);
        helper(root.right,result);
    }
}
145. Binary Tree Postorder Traversal

Given a binary tree, return the postorder traversal of its nodes’ values.

Example:

Input: [1,null,2,3]
在这里插入图片描述
Output: [3,2,1]

分析:本题要求后序遍历二叉树,属于基本题,用递归的方法实现即可。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        if(root == null) return new ArrayList();
        List<Integer> result = new ArrayList<>();
        helper(root,result);
        return result;
    }
    private void helper(TreeNode root, List<Integer> result){
        if(root == null) return;
        helper(root.left,result);
        helper(root.right,result);
        result.add(root.val);
    }
}
226. Invert Binary Tree

Invert a binary tree.

Example:

Input:
在这里插入图片描述
Output:
在这里插入图片描述
分析:本题要求反转二叉树,可以使用递归的思想。若当前节点为空返回null,否则交换当前节点的左右孩子。递归执行它的左孩子和右孩子,最终返回root。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null)
            return null;
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }
}
230. Kth Smallest Element in a BST

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.
Note: You may assume k is always valid, 1 ≤ k ≤ BST’s total elements.

Example 1:

Input: root = [3,1,4,null,2], k = 1
在这里插入图片描述
Output: 1

Example 2:

Input: root = [5,3,6,2,4,null,null,1], k = 3
在这里插入图片描述
Output: 3

分析:本题求解二叉排序树中第k小的数值。起初,我的思路是将二叉排序树中序遍历,所得的结果即为一个递增的序列,再从其中去第k小的数,显然这种做法的效率较低,不值得推荐。后来,我学习了别人提供的解法:借助helper函数,它是用来求解当前节点及其孩子节点的节点数之和。其中,若当前节点为空,返回0。否则,递归求解当前节点的左孩子和右孩子的节点个数。如果第k小的节点在右子树中,需要将k更新为k-leftCount-1。当k等于leftCount+1时,当前对象即为所求得的第k小的值。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public static int result = 0;
    public int kthSmallest(TreeNode root, int k) {
        helper(root,k);
        return result;
    }
    private int helper(TreeNode root, int k){
        if(root == null) return 0;
        int leftCount = helper(root.left, k);
        int rightCount = helper(root.right, k-leftCount-1);
        if(k == leftCount + 1)
            result = root.val;
        return leftCount + rightCount + 1;
    }
}
235. Lowest Common Ancestor of a Binary Search Tree

Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]在这里插入图片描述
Example 1:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The LCA of nodes 2 and 8 is 6.

Example 2:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

Note:
All of the nodes’ values will be unique.
p and q are different and both values will exist in the BST.

分析:本题求两个节点的共同最近祖先,可以使用递归的思想来解决。若当前节点值比两个节点值都大,则递归求解当前节点的左孩子;若当前节点值比两个节点值都小,则递归求解当前节点的右孩子;其他情况(即当前节点值大于等于一个节点值且小于等于另一个节点值),则返回当前节点,即当前节点即为所求的两个节点的共同最近祖先。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.val > p.val && root.val > q.val){
            return lowestCommonAncestor(root.left, p, q);
        }else if(root.val < p.val && root.val < q.val){
            return lowestCommonAncestor(root.right, p, q);
        }else{
            return root;
        }
    }
}
257. Binary Tree Paths

Given a binary tree, return all root-to-leaf paths.
Note: A leaf is a node with no children.

Example:

Input:
在这里插入图片描述
Output: [“1->2->5”, “1->3”]
Explanation: All root-to-leaf paths are: 1->2->5, 1->3

分析:本题要求深度遍历搜索输出二叉树的所有路径,可以使用递归的思想来解决。这里需要借助helper函数,并将当前节点、当前节点前面的路径和存储最终结果的paths作为函数的输入参数。在helper函数中,若当前节点不为空且为叶子节点,则在结果paths中加入当前路径,表示为parents+root.val;若当前节点不为空且存在左孩子,则递归调用helper函数遍历它的左孩子,这里注意函数的第二个输入参数为parents + root.val + “->”;同理,若当前节点不为空且存在右孩子,则递归调用helper函数遍历它的右孩子。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> paths = new ArrayList<>();
        helper(root, "", paths);        
        return paths;
    }
    private void helper(TreeNode root, String parents, List<String> paths){
        if(root != null && root.left == null && root.right == null)
            paths.add(parents + root.val);
        if(root != null && root.left != null)
            helper(root.left, parents + root.val + "->", paths);
        if(root != null && root.right != null)
            helper(root.right, parents + root.val + "->", paths);
    }
}
404. Sum of Left Leaves

Find the sum of all left leaves in a given binary tree.

Example:
在这里插入图片描述
There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.

分析:本题求解所有左叶子节点的和,可以用递归的思想来解决。首先定义一个全局变量sum,若当前节点为空返回0;若当前节点的左孩子不为空且为叶子节点时,将左叶子的值加入到sum中。递归求解当前节点的左孩子和右孩子,将所有符合条件的左叶子节点的值都加入到sum中。

优化的代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int sum = 0;
    public int sumOfLeftLeaves(TreeNode root) {
        if(root == null) return 0;
        if(root.left != null && root.left.left == null && root.left.right == null)
            sum += root.left.val;
        sumOfLeftLeaves(root.left);
        sumOfLeftLeaves(root.right);
        return sum;
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值