在此记录刷力扣时遇到的一些技巧-树
判断两树是否相同
【100】给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q == null){
return true;
}
if(p!=null && q!=null && p.val==q.val){
return isSameTree(p.left,q.left) &&isSameTree(p.right,q.right);
}
else
return false;
}
此题进阶
【572】另一棵树的子树
class Solution {
// 这个就是LeetCode100 题的那个函数
public boolean isSameTree(TreeNode s,TreeNode t){
// 同时为空 说明树一起到底,两树相同
if (s==null && t == null){
return true;
}
// 如果上面没有返回值,说明必有一个没有为空(有可能两个都不为空)
if (s == null || t == null){
return false;
}
// 如果判断到了这一步,说明两个都不为空
// 先序遍历 自己--左 -- 右
if (s.val != t.val){
return false;
}
return isSameTree(s.left,t.left) && isSameTree(s.right,t.right);
}
public boolean isSubtree(TreeNode s, TreeNode t) {
// 我s都遍历完了。你居然还没匹配上。那就返回false
if (s==null){
return false;
}
// 短路运算符,有一个为真,返回真
return isSameTree(s,t) || isSubtree(s.left,t) || isSubtree(s.right,t);
}
}
树的层次遍历
if (root == null) {
return new LinkedList<>();
}
List<List<Integer>> nodes = new LinkedList<>();
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
int size = q.size();
List<Integer> childNodes = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode cur = q.poll();
childNodes.add(cur.val);
if (cur.left != null) {
q.offer(cur.left);
}
if (cur.right != null) {
q.offer(cur.right);
}
}
nodes.add(childNodes);
}
return nodes;
如果求“之”字形”呢?
只需在添加子数组时偶数列反转即可!
if (flag % 2 != 0)
list.add(temp);
else {
Collections.reverse(temp);
list.add(temp);
}
flag++;
如果求深度呢?
递归
public int TreeDepth(TreeNode root) {
if(root == null) return 0 ;
return Math.max(TreeDepth(root.left),TreeDepth(root.right))+1 ;
}
非递归
public int TreeDepth(TreeNode pRoot)
{
if(pRoot == null){
return 0;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(pRoot);
int depth = 0, count = 0, nextCount = 1;
while(queue.size()!=0){
TreeNode top = queue.poll();
count++;
if(top.left != null){
queue.add(top.left);
}
if(top.right != null){
queue.add(top.right);
}
if(count == nextCount){
nextCount = queue.size();
count = 0;
depth++;
}
}
return depth;
}
树的先序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> lis = new ArrayList<>();
p(root,lis);
return lis;
}
public void p(TreeNode root,List lis){
if(root == null) return ;
lis.add(root.val);//中序遍历和后序遍历同理
p(root.left,lis);
p(root.right,lis);
}
}
扩展到n叉树
class Solution {
List<Integer> res = new ArrayList<Integer>();
public List<Integer> preorder(Node root) {
//递归版
if(root == null)
return res;
res.add(root.val);
for(Node child:root.children)
{
preorder(child);
}
return res;
}
}
class Solution {
public List<Integer> preorder(Node root) {
//非递归版
List<Integer> res = new ArrayList<Integer>();
Stack<Node> stack = new Stack<Node>();
if(root == null)
return res;
stack.push(root);
while(!stack.isEmpty())
{
Node node = stack.pop();
res.add (node.val);
for(int i = node.children.size()-1;i>= 0;i--)
{
stack.add(node.children.get(i));
}
}
return res;
}
}
3.二叉树先序中序后序排序
给定一棵二叉树,分别按照二叉树先序,中序和后序打印所有的节点。
public class Solution {
/**
*
* @param root TreeNode类 the root of binary tree
* @return int整型二维数组
*/
public ArrayList<Integer> one = new ArrayList<>();
public ArrayList<Integer> two = new ArrayList<>();
public ArrayList<Integer> there = new ArrayList<>();
public int[][] threeOrders (TreeNode root) {
// write code here
one(root);
two(root);
there(root);
int[][] res = new int[3][one.size()];
int i = 0 ;
for (int j = 0; j < one.size(); j++) {
res[i][j] = one.get(j);
}
i++;
for (int j = 0; j < two.size(); j++) {
res[i][j] = two.get(j);
}
i++;
for (int j = 0; j < there.size(); j++) {
res[i][j] = there.get(j);
}
return res;
}
public void one(TreeNode root){
if(root == null ) return ;
one.add(root.val);
one(root.left);
one(root.right);
}
public void two(TreeNode root){
if(root == null ) return ;
two(root.left);
two.add(root.val);
two(root.right);
}
public void there(TreeNode root){
if(root == null ) return ;
there(root.left);
there(root.right);
there.add(root.val);
}
}
4.二叉树层序遍历
给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
// write code here
ArrayList<ArrayList<Integer>> arr = new ArrayList<ArrayList<Integer>>() ;
if (root == null ) return arr ;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root) ;
while (!queue.isEmpty()){
ArrayList<Integer> a = new ArrayList<Integer>() ;
int len = queue.size();
for(int i = 0 ; i < len ; i ++ ){
TreeNode head = queue.poll();
a.add(head.val);
if(head.left != null) queue.add(head.left) ;
if(head.right != null) queue.add(head.right) ;
}
arr.add(a) ;
}
return arr ;
}
判断是否为完全二叉树
boolean all(TreeNode root){
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
boolean flag = false;
while(queue.size() != 0){
TreeNode newroot = queue.poll();
TreeNode left = newroot.left;
TreeNode right = newroot.right;
if ( (left == null && right != null) || // 无左子树有右子树
(flag && !(left == null && right == null)) ) //有残缺且非叶节点
return false;
if (left != null) queue.add(left);
if (right != null) queue.add(right);
// 存在残缺节点
if (left == null || right == null) flag = true;
}
return true;
}
重建二叉树
给定节点数为 n 二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
//数组长度为0的时候要处理
if(pre.length == 0) return null ;
//数组长度仅为1的时候就要处理
if(pre.length == 1) return new TreeNode(pre[0]) ;
TreeNode root = new TreeNode(pre[0]) ;
int i = 0 ;
//我们先找到root所在的位置,确定好前序和中序中左子树和右子树序列的范围
for(i = 0 ; i < vin.length ; i ++){
if(pre[0] == vin[i]) break ;
}
//递归,假设root的左右子树都已经构建完毕,那么只要将左右子树安到root左右即可
//这里注意Arrays.copyOfRange(int[],start,end)是[)的区间
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre , 1 , i+1) , Arrays.copyOfRange(vin , 0 , i)) ;
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre , i+1 , pre.length),Arrays.copyOfRange(vin , i+1 , vin.length)) ;
return root ;
}