剑指offer 树 递归
题目
剑指 Offer 55 - II. 平衡二叉树
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
public boolean isBalanced(TreeNode root) {
if(root==null) return true;
return Math.abs(height(root.left)-height(root.right))<=1
&&isBalanced(root.left)&&isBalanced(root.right);
}
public int height(TreeNode root){
if(root==null) return 0;
return Math.max(height(root.left),height(root.right))+1;
}
剑指 Offer 28. 对称的二叉树
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
return helper(root.left,root.right);
}
public boolean helper(TreeNode A,TreeNode B){
if(A==null&&B==null) return true;
if(A==null||B==null) return false;
return A.val==B.val&&helper(A.right,B.left)&&helper(A.left,B.right);
}
剑指 Offer 27. 二叉树的镜像
public TreeNode mirrorTree(TreeNode root) {
if(root==null) return root;
TreeNode temp=mirrorTree(root.left);
root.left=mirrorTree(root.right);
root.right=temp;
return root;
}
剑指 Offer 32 - I. 从上到下打印二叉树
public int[] levelOrder(TreeNode root) {
ArrayList<Integer> list=new ArrayList<>();
ArrayList<TreeNode> stack=new ArrayList<>();
if(root==null)return new int[0];
stack.add(root);
while(!stack.isEmpty()){
TreeNode node=stack.remove(0);
if(node.left!=null){
stack.add(node.left);
}
if(node.right!=null){
stack.add(node.right);
}
list.add(node.val);
}
int Array[]=new int[list.size()];
int j=0;
int i=0;
while(j<list.size()){
Array[j++]=list.get(i++);
}
return Array;
}
剑指 Offer 32 - II. 从上到下打印二叉树 II
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res=new ArrayList<>();
Queue<TreeNode> stack=new LinkedList<>();
if(root!=null) stack.add(root);
while(!stack.isEmpty()){
List<Integer> list=new ArrayList<>();
int n=stack.size();
for (int i = 0; i <stack.size() ; i++) {
TreeNode temp=stack.poll();
list.add(temp.val);
if(temp.left!=null) stack.add(temp.left);
if(temp.right!=null) stack.add(temp.right);
}
res.add(list);
}
return res;
}
剑指 Offer 32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
public List<List<Integer>> levelOrder ( TreeNode root) {
List<List<Integer>> res=new ArrayList<>();
Queue<TreeNode> stack=new LinkedList<>();
if(root!=null) stack.add(root);
while(!stack.isEmpty()){
LinkedList<Integer> list=new LinkedList<>();
int n=stack.size();
for (int i = 0; i <n ; i++) {
TreeNode node=stack.poll();
// list.add(node.val);
if(res.size()%2==0)
list.addLast(node.val);
else
list.addFirst(node.val);
if(node.left!=null) stack.add(node.left);
if(node.right!=null) stack.add(node.right);
}
res.add(list);
}
return res;
}
剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
public boolean verifyPostorder(int[] postorder) {
//左<根<右
return dfs(postorder,0,postorder.length-1);
}
public boolean dfs(int arr[],int l,int r){
if(l>=r) return true;
int p=l;
//向右遍历找最左子树的根结点下一个节点
while(arr[p]<arr[r]) p++;
int m=p;
while(arr[p]>arr[r]) p++;
return p==r&&dfs(arr,l,m-1)&&dfs(arr,m,r-1);
}
剑指 Offer 34. 二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
ArrayList<Integer> list=new ArrayList<>();
ArrayList<List<Integer>> res=new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int sum) {
recur(root,sum);
return res;
}
public void recur(TreeNode root,int sum){
if(root==null) return;
sum-=root.val;
list.add(root.val);
if(sum==0&&root.left==null&&root.right==null){
res.add(new ArrayList(list));
}
recur(root.left,sum);
recur(root.right,sum);
//把左节点放进去再放右结点
list.remove(list.size()-1);
}
面试题34 二叉树中和为某一值的路径
给定一个二叉树和一个值 sum ,判断是否有从根节点到叶子节点的节点值之和等于 sum 的路径,
public boolean hasPathSum (TreeNode root, int sum) {
if(root==null) return false;
if(sum-root.val==0&&root.left==null&&root.right==null) return true;
return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val);
}
}
##Leetcode 437. 路径总和 III
/**
* 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 {
int count=0;
public int pathSum(TreeNode root, int sum) {
if(root==null) return 0;
//找和为sum的所有路径值
dfs(root,sum);
//从左子节点寻找路径
pathSum(root.left,sum);
//从右子节点寻找路径
pathSum(root.right,sum);
return count;
}
public void dfs(TreeNode root,int sum){
if(root==null) return ;
sum-=root.val;
if(sum==0) count++;
dfs(root.left,sum);
dfs(root.right,sum);
}
}
剑指 Offer 68 - II. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null||root==p||root==q) return root;
TreeNode left=lowestCommonAncestor( root.left,p,q);
TreeNode right=lowestCommonAncestor( root.right,p,q);
if(left==null) return right;
if(right==null) return left;
return root;
}
面试题57 二叉树的下一个节点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
//树空
if(pNode==null){
return null;
}
//结点存在右子树,下一个结点为pNode右子树的左节点
if(pNode.right!=null){
pNode = pNode.right;//当前节点的右子节点
while(pNode.left!=null){
pNode=pNode.left;
}
return pNode;
}
//结点不存在右子树,pNode为左节点,下一个结点为该节点父节点;否则继续向上找
while(pNode.next!=null){
if( pNode.next.left==pNode)
return pNode.next;
pNode=pNode.next;
}
return null;
}
面试题07 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length==0||inorder.length==0) return null;
int n=inorder.length;
int root= preorder[0];
//找到中序遍历i的序列号index
int index = 0;
for (int i = 0; i < n; i++) {
if(inorder[i]==root ){
index=i;
break;
}
}
TreeNode root1=new TreeNode(root);
root1.left=buildTree(Arrays.copyOfRange(preorder,1,index+1),Arrays.copyOfRange(inorder,0,index));
root1.right=buildTree(Arrays.copyOfRange(preorder,index+1,n),Arrays.copyOfRange(inorder,index+1,n));
return root1;
}
剑指 Offer 36. 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
class Solution {
// 1. 中序,递归,来自解题大佬
Node pre, head;
public Node treeToDoublyList(Node root) {
// 边界值
if(root == null) return null;
dfs(root);
// 题目要求头尾连接
head.left = pre;
pre.right = head;
// 返回头节点
return head;
}
void dfs(Node cur) {
// 递归结束条件
if(cur == null) return;
dfs(cur.left);
// 如果pre为空,就说明是第一个节点,头结点,然后用head保存头结点,用于之后的返回
if (pre == null) head = cur;
// 如果不为空,那就说明是中间的节点。并且pre保存的是上一个节点,
// 让上一个节点的右指针指向当前节点
else if (pre != null) pre.right = cur;
// 再让当前节点的左指针指向父节点,也就连成了双向链表
cur.left = pre;
// 保存当前节点,用于下层递归创建
pre = cur;
dfs(cur.right);
}
}