剑指offer--二叉树题目详解汇总(java版)

二叉树题目汇总(持续更新)

二叉树的下一个节点
详解对称的二叉树
按之字形顺序打印二叉树
把二叉树打印成多行
序列化二叉树
二叉搜索树的第k个节点
二叉树的深度
平衡二叉树
重建二叉树.
树的子结构
二叉树的镜像
从上往下打印二叉树
二叉搜索树的后序遍历
二叉树中和为某一值的路径
二叉搜索树与双向链表

树的子结构

题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean result = false;
        if(root1 != null && root2 != null){
            if(root1.val == root2.val){
               result = doesTree1hasTree2(root1,root2);
            }
            if(!result){
                return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
            }
        }
        return result;
    }
    public boolean doesTree1hasTree2(TreeNode node1,TreeNode node2){
        if(node2 == null) return true;
        if(node1 == null) return false;
        if(node1.val != node2.val){
            return false;
        }else{
            return doesTree1hasTree2(node1.left,node2.left)&&
                doesTree1hasTree2(node1.right,node2.right);

        }
    }
}

二叉树的镜像

题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树

思路

算法步骤:
  1.节点为空直接返回
  2.如果这个节点的左右子树不为空,就交换。
  3.递归对这个节点的左子树进行求镜像。对这个节点的右子树求镜像。
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public void Mirror(TreeNode root) {
        if(root == null) return;
        //注意此处的条件是||,而不是&&!!!!
        if(root.left != null || root.right != null){
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            Mirror(root.left);
            Mirror(root.right);
        }
    }
}

从上往下打印二叉树

题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路

利用队列辅助实现.
注意Queue是abstract的,不能直接new对象。

import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        if(root == null) return list;
        list.add(root.val);
        queue.add(root);        
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            if(node.left != null){
                queue.add(node.left);
                list.add(node.left.val);
            }
            if(node.right != null){
                queue.add(node.right);
                list.add(node.right.val);
            }
        }      
        return list;
    }
}

二叉搜索树的后序遍历

题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路

算法步骤:
1.后序遍历的最后一个值为root,在前面的数组中找到第一个大于root值的位置,即为右子树开始的地方。
2.这个位置的前面是root的左子树,右边是右子树。然后左右子树分别进行这个递归操作。
3.其中,如果右边子树中有比root值小的直接返回false

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
    	if (sequence == null || sequence.length == 0) 
			return false;
    	return IsBST(sequence, 0, sequence.length -1);	
    }
    public boolean IsBST(int [] sequence, int start, int end) {
    	if(start >= end) //注意这个条件的添加
    	               // 如果对应要处理的数据只有一个或者已经没
                      //有数据要处理(start>end)就返回true
    		return true;
    	int index = start;
    	for (; index < end; index++) {//寻找大于root的第一个节点,然后再分左右两部分
			if(sequence[index] > sequence[end])
				break;
		}
        for (int i = index; i < end; i++) {//若右子树有小于根节点的值,直接返回false
			if (sequence[i] < sequence[end]) {
				return false;
			}
		}
        return IsBST(sequence, start, index-1) && IsBST(sequence, index, end-1);
	}
    
}

二叉树中和为某一值的路径

题目描述
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路

先保存根节点,然后分别递归在左右子树中找目标值,若找到即到达叶子节点,打印路径中的值

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }
}
*/
public class Solution {
    ArrayList<Integer> path = new ArrayList<>();
    ArrayList<ArrayList<Integer>> paths = new ArrayList<>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        if(root == null) return paths;
        path.add(root.val);
        target -= root.val;
        if(target ==0 && root.left == null && root.right == null){
            paths.add(new ArrayList<Integer>(path));
        }
        FindPath(root.left,target);
        FindPath(root.right,target);
        path.remove(path.size()-1);
        return paths;
    }
}

二叉搜索树与双向链表

题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路

参考:https://blog.csdn.net/weixin_40928253/article/details/85373191
方法二:递归版
解题思路:
1.将左子树构造成双链表,并返回链表头节点。
2.定位至左子树双链表最后一个节点。
3.如果左子树链表不为空的话,将当前pRootOfTree追加到左子树链表。
4.将右子树构造成双链表,并返回链表头节点。
5.如果右子树链表不为空的话,将该链表追加到pRootOfTree节点之后。
6.根据左子树链表是否为空确定返回的节点。

public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree==null)
            return null;
        if(pRootOfTree.left==null&&pRootOfTree.right==null)
            return pRootOfTree;
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(pRootOfTree.left);
        TreeNode p = left;
        // 2.定位至左子树双链表最后一个节点
        while(p!=null&&p.right!=null){
            p = p.right;
        }
        // 3.如果左子树链表不为空的话,将当前pRootOfTree追加到左子树链表
        if(left!=null){
            p.right = pRootOfTree;
            pRootOfTree.left = p;
        }
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(pRootOfTree.right);
        // 5.如果右子树链表不为空的话,将该链表追加到pRootOfTree节点之后
        if(right!=null){
            right.left = pRootOfTree;
            pRootOfTree.right = right;
        }
        return left!=null?left:pRootOfTree;
    }
}

你可能感兴趣的:(剑指offer)