目录
树的深度:相对概念。每一层的深度不同。根节点的深度为1.
树的高度:最大的深度是高度。
满二叉树:每一层都放满。层数为K,结点总数为2的k次方-1
完全二叉树:每一层从左到右依次存放。
解题思路:
要点1:前、中、后序的遍历顺序相同,只是输出root的时机不同。
实现代码:
- // 前序
- class Solution {
- public List
preorderTraversal(TreeNode root) { - List
result = new ArrayList<>(); - if(root == null){
- return result;
- }
- result.add(root.val);
- List
leftTree = preorderTraversal(root.left); - result.addAll(leftTree);
- List
rightTree = preorderTraversal(root.right); - result.addAll(rightTree);
- return result;
- }
- }
- // 中序
- class Solution {
- private List
result = new ArrayList<>(); - public List
inorderTraversal(TreeNode root) { - if(root == null){
- return result;
- }
- inorderTraversal(root.left);
- result.add(root.val);
- inorderTraversal(root.right);
- return result;
- }
- }
- // 后序
- class Solution {
- public List
postorderTraversal(TreeNode root) { - List
result = new ArrayList<>(); - if(root == null){
- return result;
- }
- List
leftTree = postorderTraversal(root.left); - result.addAll(leftTree);
- List
rightTree = postorderTraversal(root.right); - result.addAll(rightTree);
- result.add(root.val);
- return result;
- }
- }
OJ链接:
- class Solution {
- public List
preorderTraversal(TreeNode root) { - List
result = new ArrayList<>(); - if(root == null){
- return result;
- }
- Stack
stack = new Stack(); - // 这个循环就是:按照中序遍历顺序,一直往下走,将所有遇到的不为null的节点记录下来
- while(root != null || !stack.empty()){
- while(root != null){
- stack.push(root);
- result.add(root.val);
- root = root.left;
- }
- // 走到这,root为空。以示例一为例,证明走到了3.left这个节点
- // 需要先将3这个节点从stack中拿出来,这样才能遍历他的右节点
- TreeNode tmp = stack.pop();
- root = tmp.right; // 现在到了3的右节点,假设他有,现在需要回到while
- }
- return result;
- }
- }
- class Solution {
- public List
inorderTraversal(TreeNode root) { - List
result = new ArrayList<>(); - Stack
stack = new Stack(); - if(root == null) return result;
- while(root != null || !stack.empty()){
- while(root != null){
- stack.push(root);
- root = root.left;
- }
- TreeNode tmp = stack.pop();
- result.add(tmp.val);
- root = tmp.right;
- }
- return result;
- }
- }
- class Solution {
- public int pos;
- public TreeNode buildTree(int[] inorder, int[] postorder) {
- if(inorder == null || postorder == null){
- return null;
- }
- pos = postorder.length-1;
- return buildTree1(inorder,postorder,0,inorder.length-1);
-
-
- }
- public TreeNode buildTree1(int[] inorder, int[] postorder,int begin,int end){
- if(begin > end || begin < 0){
- return null;
- }
- int data = postorder[pos];
-
- TreeNode root = new TreeNode(data);
- int rootPos = findPos(inorder,data,begin,end);
- pos--;
- // 左右根 是从中序遍历的结果的最后一个节点往前找,因此,确定根节点后,应该先确定root.right
- root.right = buildTree1(inorder,postorder,rootPos+1,end);
- root.left = buildTree1(inorder,postorder,begin,rootPos-1);
- return root;
-
- }
- public int findPos(int[] inorder,int data,int begin,int end){
- for(int i=begin;i<=end;i++){
- if(inorder[i] == data){
- return i;
- }
- }
- return -1;
- }
- }
OJ链接:102. 二叉树的层序遍历 - 力扣(LeetCode)
解题思路:
要点1:定义一个队列实现层序遍历。队列中存放的是下一层的节点个数,队列的size就是下一层的节点数量。在遍历这一层的时候,将下一层的节点加入队列中
实现代码:
- class Solution {
- public List
> levelOrder(TreeNode root) {
- List
> result = new ArrayList<>();
- Queue
queque = new LinkedList<>(); - if(root == null){
- return result;
- }
- queque.offer(root);
- while(!queque.isEmpty()){
- List
tmp = new ArrayList<>(); - int size = queque.size();
- // 第一层 size = 1 ,将root的左右节点加入
- // 第二次 size = 2,while循环2次,将 root.left和root.right的左右节点加入
- while(size > 0){
- TreeNode top = queque.poll();
- tmp.add(top.val);
- if(top.left != null){
- queque.offer(top.left);
- }
- if(top.right != null){
- queque.offer(top.right);
- }
- size--;
- }
- result.add(tmp);
- }
- return result;
- }
- }
剑指 Offer II 046. 二叉树的右侧视图 - 力扣(LeetCode)
- class Solution {
- public List
rightSideView(TreeNode root) { - List
> olderLevelRsult = orderLevel(root);
- List
result = new ArrayList<>(); - if(root == null){
- return result;
- }
-
- for(List
tmp : olderLevelRsult){ -
- result.add(tmp.get(tmp.size()-1));
- }
- return result;
- }
-
- public List
> orderLevel(TreeNode root){
- List
> result = new ArrayList<>();
- Queue
queue = new LinkedList<>(); - if(root == null){
- return result;
- }
- queue.offer(root);
- while(!queue.isEmpty()){
- List
tmp = new ArrayList<>(); - int size = queue.size();
- while(size >0){
- TreeNode top = queue.poll();
- tmp.add(top.val);
- if(top.left != null){
- queue.offer(top.left);
- }
- if(top.right != null){
- queue.offer(top.right);
- }
- size--;
- }
- result.add(tmp);
- }
- return result;
- }
- }
解题思路:
遍历求解:挨个遍历,采用前序遍历的思路,如果root!=null,size++
子问题思路:左树+右树+1
实现代码:
- // 子问题思路
- // 获取总节点个数
- public int getSize(TreeNode root){
- if(root == null){
- return 0;
- }
- int left = getSize(root.left);
- int right = getSize(root.right);
- return 1+left+right;
- }
- // 遍历思路
- public int size = 0;
- private void getSize2(TreeNode root){
- if(root == null){
- return;
- }
- size++;
- getSize2(root.left);
- getSize2(root.right);
- }
解题思路:
要点1:叶子节点的判断条件:root.left==null&&root.right==null
实现代码:
- // 获取叶子节点个数
- public int num = 0;
- public void getLeafSize1(TreeNode root){
- if(root == null){
- return;
- }
- if(root.left==null && root.right == null){
- num++;
- }
- getLeafSize1(root.left);
- getLeafSize1(root.right);
- }
- public int getLeafSize2(TreeNode root){
- if(root == null){
- return 0;
- }
- if(root.left==null && root.right == null){
- return 1;
- }
- int left = getLeafSize1(root.left);
- int right = getLeafSize2(root.right);
- return left+right;
- }
解题思路:

当k=1,证明到达第K层,返回1.不需要再向下遍历。
实现代码:
- public int getKLevelSize(TreeNode root,int k){
- if(root == null){
- return 0;
- }
- if(k==1){
- return 1;
- }
- int left = getKLevelSize(root.left,k-1);
- int right = getKLevelSize(root.right,k-1);
- return left+right;
- }
- public int KLevelSize = 0;
- public int getKLevelSize2(TreeNode root,int k){
- if(root == null){
- return 0;
- }
- if(k==1){
- KLevelSize++;
- }
- getKLevelSize(root.left,k-1);
- getKLevelSize(root.right,k-1);
- }
问题描述:

解题思路:
要点1:先判断结构。再判断值。使用前序遍历的方式。
要点2:如果两个根节点都为null,认为这两个节点相同,返回true
要点3:如果根节点有一个不为null,结果不相同,返回false
要点4:如果都不为null。先判断值是否相同,不相同就返回false。相同,则接着判断这两个根的左节点和右节点
实现代码:
- class Solution {
- public boolean isSameTree(TreeNode p, TreeNode q) {
- if(p == null && q == null){
- return true;
- }
- if(p == null || q==null){
- return false;
- }
- // 走到这,都不为null,判断值
- if(p.val != q.val){
- return false;
- }else{
- return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
- }
- }
- }
OJ链接:572. 另一棵树的子树 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:采用判断两个树是否相同的思路。
要点2:如果subRoot是个空,返回true。空树是任何树的子树
要点3:如果root是空,返回false。空树没有子树
要点4:先判断root这整棵树和subRoot是否相等、不相等,接着判断
root的左子树不为空的情况下,root的左子树这颗树和subRoot是否相等,不相等,接着判断
root的右子树不为空的情况下, root的右子树这颗树和subRoot是否相等
实现代码:
- class Solution {
- public boolean isSubtree(TreeNode root, TreeNode subRoot) {
- if(subRoot == null) return true;
- if(root == null) return false;
- if(isSameTree(root,subRoot)){
- return true;
- }
- // 注意注意!!!判断的是:subRoot这棵树是否是root.left这棵树的子树
- if(root.left != null && isSubtree(root.left,subRoot)){
- return true;
- }
- if(root.right != null && isSubtree(root.right,subRoot)){
- return true;
- }
- return false;
-
- }
- public boolean isSameTree(TreeNode root, TreeNode subRoot) {
- if(root == null && subRoot==null) return true;
- if(root == null || subRoot == null) return false;
- if(root.val != subRoot.val) return false;
- return isSameTree(root.left,subRoot.left)&&isSameTree(root.right,subRoot.right);
- }
- }
OJ链接:104. 二叉树的最大深度 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:root==null,返回0。
要点2:root不为空,返回1+max(左子树的高度,右子树的高度)
实现代码:
- class Solution {
- public int maxDepth(TreeNode root) {
- if(root == null){
- return 0;
- }
- return 1+Math.max(maxDepth(root.left),maxDepth(root.right));
- }
- }
OJ链接:110. 平衡二叉树 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:求每个节点的左树的高度和右树的高度,相减判断是否满足平衡二叉树的要求,时间复杂度是O(n2)
实现代码:
- class Solution {
- public boolean isBalanced(TreeNode root) {
- if(root == null){
- return true;
- }
- int left = maxDepth(root.left);
- int right = maxDepth(root.right);
- if(Math.abs(left - right) > 1){
- return false;
- }
- // root判断完后,需要接着判断左子树和右子树是否平衡
- return isBalanced(root.left)&&isBalanced(root.right);
-
- }
- public int maxDepth(TreeNode root){
- if(root == null){
- return 0;
- }
- return 1+Math.max(maxDepth(root.left),maxDepth(root.right));
- }
- }
解题思路:
要点1:在刚刚的解法中,时间复杂度是O(n2),现在要使时间复杂度使O(n).
可以在递归的过程中,计算出左右子树的高度,判断高度是否<=1,如果不满足,返回-1.则证明不平衡
实现代码:
- class Solution {
- public boolean isBalanced(TreeNode root) {
-
- return maxDepth(root) >= 0;
-
- }
- public int maxDepth(TreeNode root){
- if(root == null){
- return 0;
- }
- int left = maxDepth(root.left);
- int right = maxDepth(root.right);
-
- if(left >= 0 && right >=0 && Math.abs(left - right) <= 1){
- return 1+Math.max(left,right);
- }
- return -1;
- }
- }
OJ链接:101. 对称二叉树 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:如果root为空,则返回true。
要点2:写一个函数,输入是左树的根节点和右树的根节点
要点3:如果这连两个根节点不同时为null,返回false。同时为null,返回true。都不为null。接着判断两个根节点的值是否一样。一样接着判断左节点的左子树和右节点的右子树、左节点的右子树和右节点的左子树是否是对称的。

实现代码:
- class Solution {
- public boolean isSymmetric(TreeNode root) {
- if(root == null){
- return true;
- }
- return isSymmetricChild(root.left,root.right);
-
- }
- public boolean isSymmetricChild(TreeNode leftNode,TreeNode rightNode){
- if(leftNode == null && rightNode==null){
- return true;
- }
- if(leftNode == null && rightNode != null || leftNode != null && rightNode == null ){
- return false;
- }
- if(leftNode.val != rightNode.val){
- return false;
- }
- return isSymmetricChild(leftNode.left,rightNode.right)&&isSymmetricChild(leftNode.right,rightNode.left);
-
- }
- }
OJ链接:二叉树遍历_牛客题霸_牛客网 (nowcoder.com)
实现代码:
- import java.util.*;
- public class Main{
- public static void main(String[] args){
- Scanner scan = new Scanner(System.in);
- while(scan.hasNext()){
- String str1 = scan.nextLine();
- TreeNode root = creatTree(str1);
- midorder(root);
-
- }
- }
- public static void midorder(TreeNode root){
- if(root == null){
- return;
- }
- midorder(root.left);
- System.out.print(root.val + " ");
- midorder(root.right);
- }
- public static int i;
- public static TreeNode creatTree(String str){
-
- TreeNode root = null;
- char ch1 = str.charAt(i);
- if(ch1 != '#'){
- root = new TreeNode(ch1);
- i++;
- root.left = creatTree(str);
- root.right = creatTree(str);
- }else{
- i++;
- }
- return root;
- }
- }
- class TreeNode{
- public char val;
- public TreeNode left;
- public TreeNode right;
- public TreeNode(char val){
- this.val = val;
- }
- }
OJ链接:236. 二叉树的最近公共祖先 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:如果p和q有一个等于root,就返回root。
要点2:判断p和q是否在root的左子树或者右子树中。
实现代码:
- class Solution {
- public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
- if(root == null){
- return null;
- }
- // 判断p与q是否等于root,如果等于,则证明root就是最近的公共节点
- if(p == root || q == root){
- return root;
- }
- // 判断p、q是否在root的左树里面存在,如果p或q等于左树的某个节点,就会返回这个节点的值
- TreeNode left = lowestCommonAncestor(root.left,p,q);
- // 判断p、q是否在root的右树里面存在,如果p或q等于右树的某个节点,就会返回这个节点的值
- TreeNode right = lowestCommonAncestor(root.right,p,q);
- // 如果即在左树里面存在,又在右树里面存在,就证明一个是在root的左子树中。另一个是在root的右子树中。他们的最近公共祖先是root
- if(left != null && right != null){
- return root;
- }
- // right为null,证明p、q在右子树都不存在,所以都在左子树中。所以left是最近公共祖先
- if(left != null && right == null){
- return left;
- }
- if(left == null && right != null){
- return right;
- }
- if(left == null && right == null){
- return null;
- }
- return null;
- }
- }
OJ链接:二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com)
实现代码:
- import java.util.*;
- public class Main{
- public static void main(String[] args){
- Scanner scan = new Scanner(System.in);
- while(scan.hasNext()){
- String str1 = scan.nextLine();
- TreeNode root = creatTree(str1);
- midorder(root);
-
- }
- }
- public static void midorder(TreeNode root){
- if(root == null){
- return;
- }
- midorder(root.left);
- System.out.print(root.val + " ");
- midorder(root.right);
- }
- public static int i;
- public static TreeNode creatTree(String str){
-
- TreeNode root = null;
- char ch1 = str.charAt(i);
- if(ch1 != '#'){
- root = new TreeNode(ch1);
- i++;
- root.left = creatTree(str);
- root.right = creatTree(str);
- }else{
- i++;
- }
- return root;
- }
- }
- class TreeNode{
- public char val;
- public TreeNode left;
- public TreeNode right;
- public TreeNode(char val){
- this.val = val;
- }
- }
OJ链接:
问题描述:

解题思路:
要点1:root==null,返回0。
要点2:root不为空,返回1+max(左子树的高度,右子树的高度)
实现代码:
- class Solution {
- public int maxDepth(TreeNode root) {
- if(root == null){
- return 0;
- }
- return 1+Math.max(maxDepth(root.left),maxDepth(root.right));
- }
- }
OJ链接:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:root==null,返回0。
要点2:root不为空,返回1+max(左子树的高度,右子树的高度)
实现代码:
- class Solution {
- public int pos = 0;
- public TreeNode buildTree(int[] preorder, int[] inorder) {
- if(preorder == null || inorder == null){
- return null;
- }
- return buildTree1(preorder,inorder,0,inorder.length-1);
- }
- public TreeNode buildTree1(int[] preorder,int[] inorder,int begin,int end){
- if(begin > end){
- return null;
- }
- // 拿到前序遍历结果的第一个值
- int data = preorder[pos];
- // 第一值就是root,构建一个节点
- TreeNode root = new TreeNode(data);
- int rootPos = findIndex(inorder,data,begin,end);
- pos++;
- root.left =buildTree1(preorder,inorder,begin,rootPos-1);
- root.right = buildTree1(preorder,inorder,rootPos+1,end);
- return root;
- }
- public int findIndex(int[] inorder,int data,int begin,int end){
- // 查找data在中序遍历结果中的位置
- for(int i= begin;i<=end;i++){
- if(inorder[i] == data){
- return i;
- }
- }
- return -1;
- }
- }
OJ链接:606. 根据二叉树创建字符串 - 力扣(LeetCode)
问题描述:

解题思路:
要点1:root==null,返回0。
要点2:root不为空,返回1+max(左子树的高度,右子树的高度)
实现代码:
- class Solution {
- public StringBuffer sb = new StringBuffer();
-
- public void tree2strChild(TreeNode root) {
- if(root == null){
- return;
- }
- sb.append(root.val);
- if(root.left != null){
- sb.append("(");
- tree2strChild(root.left);
- sb.append(")");
- }else{
- if(root.right == null){
- return;
- }else{
- sb.append("()");
- }
- }
- if(root.right == null){
- return;
- }else{
- sb.append("(");
- tree2strChild(root.right);
- sb.append(")");
- }
-
- }
-
- public String tree2str(TreeNode root) {
- if(root == null){
- return null;
- }
- tree2strChild(root);
- return sb.toString();
- }
- }