深度优先遍历DFS
144.二叉树的前序遍历
145.二叉树的后序遍历
94. 二叉树的中序遍历
方法一:递归
class Solution {
//前序
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res=new ArrayList<Integer>();
preorder(root,res);
return res;
}
public void preorder(TreeNode root,List<Integer> res){
if(root==null) return;
res.add(root.val);//中
preorder(root.left,res);
preorder(root.right,res);
}
//后序
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res=new ArrayList<Integer>();
postorder(root,res);
return res;
}
public void postorder(TreeNode root,List<Integer> res){
if(root==null) return;
postorder(root.left,res);
postorder(root.right,res);
res.add(root.val);
}
//中序
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
inorder(res,root);
return res;
}
public void inorder(List<Integer> res, TreeNode root){
if(root == null) return;
inorder(res,root.left);
res.add(root.val);
inorder(res,root.right);
}
}
方法二:迭代(即用栈来模拟递归调用的过程)
class Solution {
//前序迭代
public List<Integer> preorderTraversal(TreeNode root){
List<Integer> res=new ArrayList<Integer>();
Stack<TreeNode> stack=new Stack<TreeNode>();
if(root==null) return new ArrayList<Integer>();
stack.push(root);
while(stack.size()>0){
TreeNode node=stack.pop();
res.add(node.val);
if(node.right!=null) stack.push(node.right);
if(node.left!=null) stack.push(node.left);//栈先进后出 故先放右节点
}
return res;
}
//后序迭代:与前序差不多
public List<Integer> postorderTraversal(TreeNode root){
List<Integer> res=new ArrayList<Integer>();
Stack<TreeNode> stack=new Stack<TreeNode>();
if(root==null) return new ArrayList<>();
stack.push(root);
while(stack.size()>0){
TreeNode node =stack.pop();
res.add(node.val);
if(node.left!=null) stack.push(node.left);
if(node.right!=null) stack.push(node.right);
}
Collections.reverse(res);
return res;
}
//中序迭代:与前序遍历不同,需要遍历到最左节点再开始出栈,然后转向右边继续
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
while(root!=null||stack.size()>0){
if(root!=null){
stack.push(root);
root=root.left;//一直向左找
}else{
TreeNode node=stack.pop();
res.add(node.val);
root=node.right;
}
}
return res;
}
}
方法三:迭代法 前中后序统一格式框架:添加空节点!
为了解决中序遍历时访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况不,在每次要处理的节点放入栈之后,紧接着放入一个空节点作为标记,最后出栈的时候遇到空节点就知道,它之后是要处理的节点。
public List<Integer> Traversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
if(root!=null) stack.push(root);
while(stack.size()>0){
TreeNode node=stack.peek();
if(node!=null) {
stack.pop();
//1、前序遍历的入栈顺序为 右--左--中
//2、后序遍历的入栈顺序为 中--右--左
//3、中序遍历的入栈顺序为 右--中--左
}else{//遇到空节点时弹出下一节点
stack.pop();
node=stack.pop();
res.add(node.val);
}
}
return res;
}
1、前序遍历的入栈顺序为 右–左--中
if(node.right!=null) stack.push(node.right);//右
if(node.left!=null) stack.push(node.left);//左
stack.push(node);//中
stack.push(null);//添加空节点做标记
2、后序遍历的入栈顺序为 中–右--左
stack.push(node);//中
stack.push(null);
if(node.right!=null) stack.push(node.right);//右
if(node.left!=null) stack.push(node.left);
3、中序遍历的入栈顺序为 右–中--左
if(node.right!=null) stack.push(node.right);//右
stack.push(node);//中
stack.push(null);//添加空节点做标记
if(node.left!=null) stack.push(node.left);//左
589.N叉树的前序遍历
class Solution {
//迭代框架版
public List<Integer> preorder(Node root) {
List<Integer> res=new ArrayList<Integer>();
Stack<Node> stack=new Stack<Node>();
if(root!=null) stack.push(root);
while(stack.size()>0){
Node node=stack.peek();
if(node!=null){
stack.pop();
Collections.reverse(node.children);//入栈顺序要反过来
for(Node childNode:node.children){
stack.push(childNode);
}
stack.push(node);
stack.push(null);
}else{
stack.pop();
node=stack.pop();
res.add(node.val);
}
}
return res;
}
public List<Integer> preorder(Node root) {
LinkedList<Node> stack = new LinkedList<>();
LinkedList<Integer> output = new LinkedList<>();
if (root == null) {
return output;
}
stack.add(root);
while (!stack.isEmpty()) {
Node node = stack.pollLast();
output.add(node.val);
Collections.reverse(node.children);
for (Node item : node.children) {
stack.add(item);
}
}
return output;
}
}
590.N叉树的后序遍历
class Solution {
//迭代
public List<Integer> postorder(Node root) {
List<Integer> res=new ArrayList<Integer>();
Stack<Node> stack=new Stack<Node>();
if(root!=null) stack.push(root);
while(stack.size()>0){
Node node=stack.peek();
if(node!=null){
stack.pop();
for(Node childNode:node.children){
stack.push(childNode);
}
stack.push(node);
stack.push(null);
}else{
stack.pop();
node=stack.pop();
res.add(node.val);
}
}
Collections.reverse(res);
return res;
}
}
257. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
class Solution {
//递归 深度优先遍历
public List<String> binaryTreePaths(TreeNode root) {
List<String> paths=new ArrayList<String>();
getBinaryPaths(root,"",paths);
return paths;
}
public void getBinaryPaths(TreeNode root,String path,List<String> paths){
if(root!=null){
StringBuffer pathSB=new StringBuffer(path);
pathSB.append(Integer.toString(root.val));
if(root.left==null&&root.right==null){
paths.add(pathSB.toString());
}else{
pathSB.append("->");
getBinaryPaths(root.left,pathSB.toString(),paths);
getBinaryPaths(root.right,pathSB.toString(),paths);
}
}
}
}
广度优先遍历BFS
102.二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res= new ArrayList<List<Integer>>();
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();//队列大小相当于每层节点个数
ArrayList<Integer> temp=new ArrayList<Integer>();//每层节点放入一个list集合
for(int i=0;i<size;i++){
TreeNode node=que.remove();
temp.add(node.val);
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
res.add(temp);
}
return res;
}
}
429.N叉树的层次遍历
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
LinkedList<Node> que=new LinkedList<Node>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
ArrayList<Integer> temp=new ArrayList<Integer>();
for(int i=0;i<size;i++){
Node node=que.remove();
temp.add(node.val);
for(Node childNode:node.children){//把每一层孩子节点加入集合
que.add(childNode);
}
}
res.add(temp);
}
return res;
}
}
107. 二叉树的层次遍历 II
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
翻转102的结果集即可。
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res=new ArrayList<List<Integer>>();
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
ArrayList<Integer> temp=new ArrayList<Integer>();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
temp.add(node.val);
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
res.add(temp);
}
Collections.reverse(res);//翻转list集合
return res;
}
}
104. 二叉树的最大深度==剑指55
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
此题因为是求最大深度,所以可以用层次遍历统计一共多少层。
class Solution {
public int maxDepth(TreeNode root) {
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
int depth=0;
while(que.size()>0){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
//res.add(node.val);
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
depth++;//层次遍历 每遍历一次记录一次
}
return depth;
}
// //递归
// public int maxDepth(TreeNode root){
// if(root==null) return 0;
// int leftHeight=maxDepth(root.left);
// int rightHeight=maxDepth(root.right);
// return Math.max(leftHeight,rightHeight)+1;
// }
}
559. N 叉树的最大深度
class Solution {
//递归
// public int maxDepth(Node root) {
// if(root==null) return 0;
// int depth=0;
// for(Node child:root.children){
// depth=Math.max(depth,maxDepth(child));
// }
// return depth+1;
// }
//迭代
public int maxDepth(Node root){
LinkedList<Node> que=new LinkedList<Node>();
if(root!=null) que.add(root);
int depth=0;
while(que.size()>0){
int size=que.size();
depth++;
for(int i=0;i<size;i++){
Node node=que.remove();
for(Node child:node.children){
que.add(child);
}
}
}
return depth;
}
}
111. 二叉树的最小深度
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
class Solution {
// 递归
// public int minDepth(TreeNode root) {
// if(root==null) return 0;
// int leftHeight=minDepth(root.left);
// int rightHeight=minDepth(root.right);
// return leftHeight==0||rightHeight==0?Math.max(leftHeight,rightHeight)+1:Math.min(leftHeight,rightHeight)+1;
// }
public int minDepth(TreeNode root){
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
int depth=0;
while(que.size()>0){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
if(node.left==null&&node.right==null){
return depth+1;//若遇到了叶节点 则直接返回层数+1(为什么加一 画图模拟下即可) LC上默认根节点深度为1
}
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
depth++;
}
return depth;
}
}
199. 二叉树的右视图
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res=new ArrayList<Integer>();
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
if(i==size-1) res.add(node.val);//只保存每一层最右节点
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
}
return res;
}
}
637. 二叉树的层平均值
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res=new ArrayList<Double>();
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
double sum=0;//每层节点的和
for(int i=0;i<size;i++){
TreeNode node=que.remove();
sum+=node.val;
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
res.add(sum/size);//每层节点的平均值加入结果集
}
return res;
}
}
116. 填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
class Solution {
public Node connect(Node root) {
LinkedList<Node> que=new LinkedList<Node>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
Node node=null;
Node nodePre=null;
for(int i=0;i<size;i++){
if(i==0){
nodePre=que.remove();
node=nodePre;//取出每一层的第一个节点
}else{
node=que.remove();
nodePre.next=node;//前一节点的next指向当前节点
nodePre=nodePre.next;
}
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
nodePre.next=null;//最后一个节点指向空
}
return root;
}
}
117. 填充每个节点的下一个右侧节点指针 II
与116不同的是:没规定是完美二叉树 代码相同
515. 在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res=new ArrayList<Integer>();
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
int maxVal=Integer.MIN_VALUE;
for(int i=0;i<size;i++){
TreeNode node=que.remove();
maxVal=node.val>maxVal?node.val:maxVal;//每层找最大值即可
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
res.add(maxVal);
}
return res;
}
}
226. 翻转二叉树==剑指27题
class Solution {
//递归
public TreeNode invertTree(TreeNode root) {
if(root==null) return root;//递归终止条件
TreeNode temp=root.right;
root.right=root.left;
root.left=temp;//前序遍历 先处理根节点 交换左右
invertTree(root.left);//左
invertTree(root.right);//右
return root;
}
//迭代
public TreeNode invertTree(TreeNode root){
Stack<TreeNode> stack=new Stack<TreeNode>();
if(root!=null) stack.push(root);
while(stack.size()>0){
TreeNode node=stack.pop();
TreeNode temp=node.left;
node.left=node.right;
node.right=temp; //交换左右 中
if(node.right!=null) stack.push(node.right);//右
if(node.left!=null) stack.push(node.left);//左
}
return root;
}
//迭代 统一写法
public TreeNode invertTree(TreeNode root){
Stack<TreeNode> stack=new Stack<TreeNode>();
if(root!=null) stack.push(root);
while(stack.size()>0){
TreeNode node=stack.peek();
if(node!=null){
stack.pop();
if(node.right!=null) stack.push(node.right);//右
if(node.left!=null) stack.push(node.left);//左
stack.push(node);//中
stack.push(null);
}else{
stack.pop();
node=stack.pop();
TreeNode temp=node.left;
node.left=node.right;
node.right=temp;
}
}
return root;
}
//层序遍历
public TreeNode invertTree(TreeNode root){
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
TreeNode temp=node.left;
node.left=node.right;
node.right=temp;
if(node.left!=null) que.push(node.left);
if(node.right!=null) que.push(node.right);
}
}
return root;
}
}
222. 完全二叉树的节点个数
class Solution {
//递归
// public int countNodes(TreeNode root) {
// if(root==null) return 0;
// int leftCount=countNodes(root.left);
// int rightCount=countNodes(root.right);
// int count=leftCount+rightCount+1;
// return count;
// }
//迭代 层序遍历统计遍历过得节点数
public int countNodes(TreeNode root){
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
int depth=0;
while(que.size()>0){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
depth++;
if(node.left!=null) que.add(node.left);
if(node.right!=null) que.add(node.right);
}
}
return depth;
}
}
110. 平衡二叉树==剑指55题
class Solution {
//递归
public int getDepth(TreeNode node){
if(node==null) return 0;
int leftheight=getDepth(node.left);
if(leftheight==-1) return -1;
int rightheight=getDepth(node.right);
if(rightheight==-1) return -1;
int height=Math.abs(leftheight-rightheight)>1?-1:1+Math.max(leftheight,rightheight);
return height;
}
public boolean isBalanced(TreeNode root) {
int res=getDepth(root);
if(res==-1) return false;
else return true;
}
}
100. 相同的树
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
return compare(p,q);
}
public boolean compare(TreeNode tree1,TreeNode tree2){
if(tree1==null&&tree2==null) return true;
else if(tree1!=null&&tree2==null) return false;
else if(tree1==null&&tree2!=null) return false;
else if(tree1.val!=tree2.val) return false;
// 此时就是:左右节点都不为空,且数值相同的情况
boolean outside=compare(tree1.left,tree2.left);
boolean inside=compare(tree1.right,tree2.right);
boolean isSame=outside&&inside;
return isSame;
}
}
101. 对称二叉树==剑指28题
class Solution {
//递归
// public boolean isSymmetric(TreeNode root) {
// if(root==null) return true;
// return compare(root.left,root.right);
// }
// public boolean compare(TreeNode left,TreeNode right){
// if(left==null&&right!=null) return false;
// else if(left!=null&&right==null) return false;
// else if(left==null&&right==null) return true;
// else if(left.val!=right.val) return false;
// boolean outside=compare(left.left,right.right);//外侧比较的是左节点的左孩子和右节点的右孩子
// boolean inside=compare(left.right,right.left);//内侧比较的是左节点的右孩子和右节点的左孩子
// boolean isSame=outside&&inside;
// return isSame;
// }
//迭代
public boolean isSymmetric(TreeNode root){
if(root==null) return true;
Stack<TreeNode> st=new Stack<TreeNode>();//把要比较的节点放入一个容器(队列、数组都可以)两两比较
st.push(root.left);
st.push(root.right);
while(st.size()>0){
TreeNode leftNode=st.pop();
TreeNode rightNode=st.pop();
if(leftNode==null&&rightNode==null) continue;
if((leftNode==null||rightNode==null||leftNode.val!=rightNode.val)) return false;
st.push(leftNode.left);
st.push(rightNode.right);
st.push(leftNode.right);
st.push(rightNode.left);
}
return true;
}
}
513. 找树左下角的值
class Solution {
//BFS
// public int findBottomLeftValue(TreeNode root) {
// int res = 0;
// LinkedList<TreeNode> que = new LinkedList<>();
// if(root!=null) que.add(root);
// while (que.size()>0)
// {
// int size = que.size();
// for (int i = 0; i < size; i++)
// {
// TreeNode node = que.remove();
// if (i == 0) res = node.val;//记录最左节点值
// if (node.left != null) que.add(node.left);
// if (node.right != null) que.add(node.right);
// }
// }
// return res;
// }
//BFS改进:改为从上到下,从右到左遍历,则遍历的最后一个节点肯定是最后一行最左边的值
public int findBottomLeftValue(TreeNode root) {
int res=0;
LinkedList<TreeNode> que=new LinkedList<TreeNode>();
if(root!=null) que.add(root);
while(que.size()>0){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode node=que.remove();
res=node.val;
if(node.right!=null) que.add(node.right);
if(node.left!=null) que.add(node.left);
}
}
return res;
}
}
404. 左叶子之和
class Solution {
//递归
// public int sumOfLeftLeaves(TreeNode root) {
// int sum=0;
// if(root==null) return 0;
// if(root.left!=null&&root.left.left==null&&root.left.right==null){
// sum=root.left.val;
// }
// return sum+sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right);
// }
//迭代
public int sumOfLeftLeaves(TreeNode root){
Stack<TreeNode> stack=new Stack<TreeNode>();
int sum=0;
if(root!=null) stack.push(root);
while(stack.size()>0){
TreeNode node=stack.pop();
if(node.left!=null&&node.left.left==null&&node.left.right==null){
sum+=node.left.val;
}
if(node.left!=null) stack.push(node.left);
if(node.right!=null) stack.push(node.right);
}
return sum;
}
}
572. 另一个树的子树
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if(s==null) return false;
else if(s.val==t.val&&isSame(s,t)){
return true;
}else return isSubtree(s.left,t)||isSubtree(s.right,t);
}
public boolean isSame(TreeNode tree1,TreeNode tree2){
if(tree1==null&&tree2==null) return true;
else if(tree1!=null&&tree2==null) return false;
else if(tree1==null&&tree2!=null) return false;
else if(tree1.val!=tree2.val) return false;
// 此时就是:左右节点都不为空,且数值相同的情况
boolean outside=isSame(tree1.left,tree2.left);
boolean inside=isSame(tree1.right,tree2.right);
boolean res=outside&&inside;
return res;
}
}
112. 路径总和
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root==null) return false;
return traversal(root,sum-root.val);
}
public boolean traversal(TreeNode cur,int count){
if (cur.left==null&&cur.right==null&&count == 0) return true; // 遇到叶子节点,并且计数为0
if (cur.left==null&&cur.right==null) return false; // 遇到叶子节点直接返回
if (cur.left!=null) { // 左
count -= cur.left.val; // 递归,处理节点;
if (traversal(cur.left, count)) return true;
count += cur.left.val; // 回溯,撤销处理结果
}
if (cur.right!=null) { // 右
count -= cur.right.val; // 递归,处理节点;
if (traversal(cur.right, count)) return true;
count += cur.right.val; // 回溯,撤销处理结果
}
return false;
}
}
113. 路径总和 II==剑指34
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res=new ArrayList();
List<Integer> list=new ArrayList();
backTrack(root,sum,list,res);
return res;
}
public void backTrack(TreeNode node,int sum,List<Integer> list,List<List<Integer>> res){
if(node==null) return;
list.add(node.val);
if(node.left==null&&node.right==null&&sum-node.val==0){//找到叶子节点并且和为sum
res.add(new ArrayList(list));//添加路径
list.remove(list.size()-1);
return;
}
backTrack(node.left,sum-node.val,list,res);
backTrack(node.right,sum-node.val,list,res);
list.remove(list.size()-1);
}
}
106. 从中序与后序遍历序列构造二叉树
class Solution {
HashMap<Integer,Integer> inorderMap=new HashMap<>();
int[] post;
public TreeNode buildTree(int[] inorder, int[] postorder) {
for(int i=0;i<inorder.length;i++){
inorderMap.put(inorder[i],i);
}
post=postorder;
TreeNode root=buildTree(0,inorder.length-1,0,postorder.length-1);
return root;
}
public TreeNode buildTree(int iStart,int iEnd,int pStart,int pEnd){
if(iEnd<iStart||pEnd<pStart) return null;
int root=post[pEnd];
int rootIndex=inorderMap.get(root);
TreeNode node=new TreeNode(root);//创建该节点
node.left=buildTree(iStart,rootIndex-1,pStart,pStart+rootIndex-iStart-1);//左递归
node.right=buildTree(rootIndex+1,iEnd,pStart+rootIndex-iStart,pEnd-1);//右递归
return node;
}
}
105. 从前序与中序遍历序列构造二叉树
class Solution {
HashMap<Integer, Integer> inorderMap = new HashMap<>();
int[] pre;
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i = 0; i < inorder.length; i++) {
inorderMap.put(inorder[i], i);
}
pre=preorder;
return buildTree( 0, preorder.length, 0, inorder.length);
}
private TreeNode buildTree(int p_start, int p_end, int i_start, int i_end) {
if (p_start == p_end) {
return null;
}
int root_val = pre[p_start];
TreeNode root = new TreeNode(root_val);
int i_root_index = inorderMap.get(root_val);
int leftNum = i_root_index - i_start;
root.left = buildTree( p_start + 1, p_start + leftNum + 1, i_start, i_root_index);
root.right = buildTree( p_start + leftNum + 1, p_end, i_root_index + 1, i_end);
return root;
}
}
654. 最大二叉树
给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
二叉树的根是数组中的最大元素。
左子树是通过数组中最大值左边部分构造出的最大二叉树。
右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return buildTree(nums,0,nums.length);
}
public TreeNode buildTree(int[] nums,int left,int right){
if(left>=right) return null;
int maxValIndex=left;
for(int i=left+1;i<right;i++){
if(nums[i]>nums[maxValIndex]){
maxValIndex=i;
}
}
int maxVal=nums[maxValIndex];//找到最大值作为分割点
TreeNode root=new TreeNode(maxVal);
root.left=buildTree(nums,left,maxValIndex);
root.right=buildTree(nums,maxValIndex+1,right);
return root;
}
}
617. 合并二叉树
合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
class Solution {
//递归
// public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
// if(t1==null) return t2;
// if(t2==null) return t1;
// TreeNode root=new TreeNode(0);
// root.val=t1.val+t2.val;
// root.left=mergeTrees(t1.left,t2.left);
// root.right=mergeTrees(t1.right,t2.right);
// return root;
// }
//使用队列模拟类似层序遍历
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
LinkedList<TreeNode> que=new LinkedList<>();
if(t1==null) return t2;
if(t2==null) return t1;
que.add(t1);
que.add(t2);
while(que.size()>0){
TreeNode node1=que.peek();
que.pop();
TreeNode node2=que.peek();
que.pop();
node1.val+=node2.val;
if(node1.left!=null&&node2.left!=null){
que.add(node1.left);
que.add(node2.left);
}
if(node1.right!=null&&node2.right!=null){
que.add(node1.right);
que.add(node2.right);
}
if(node1.left==null&&node2.left!=null){
node1.left=node2.left;
}
if(node1.right==null&&node2.right!=null){
node1.right=node2.right;
}
}
return t1;
}
}
98. 验证二叉搜索树
class Solution {
//递归
TreeNode pre=null;
public boolean isValidBST(TreeNode root) {
return inorderDfs(root);
}
public boolean inorderDfs(TreeNode root){
if(root==null) return true;//空树也是二叉搜索树
if(inorderDfs(root.left)){
if(pre==null){
pre=root;
}else if(pre.val>=root.val){
return false;
}else{
pre=root;
}
return inorderDfs(root.right);
}
return false;
}
//迭代
public boolean isValidBST(TreeNode root){
if(root == null) return true;
Integer preValue = null;
TreeNode node = root;
Stack<TreeNode> stack = new Stack<>();
while(stack.size() > 0 || node != null){
while(node != null){
stack.push(node);
node = node.left;
}
node = stack.pop();
if(preValue == null){
preValue = node.val;
}else if(preValue >= node.val){
return false;
}
preValue = node.val;
node = node.right;
}
return true;
}
}
530. 二叉搜索树的最小绝对差
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
class Solution {
//递归
int min=Integer.MAX_VALUE;
TreeNode pre;
public int getMinimumDifference(TreeNode root) {
inorder(root);
return min;
}
public void inorder(TreeNode root) {
if(root==null) return;
inorder(root.left);
if(pre!=null){
min=Math.min(min,root.val-pre.val);
}
pre=root;
inorder(root.right);
}
//迭代
public int getMinimumDifference(TreeNode root) {
int min=Integer.MAX_VALUE;
Stack<TreeNode> stack=new Stack<>();
TreeNode node=root;
TreeNode pre=null;
while (stack.size()>0||node!=null) {
if(node!=null){
stack.push(node);
node=node.left;
}else{
node=stack.pop();
if (pre!=null)
min = Math.min(min,node.val-pre.val);
pre=node;
node=node.right;
}
}
return min;
}
}
236. 二叉树的最近公共祖先==剑指68
class Solution {
//后序遍历 自底向上回溯
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==p||root==q||root==null) 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;
if(left==null&&right==null) return null;
return root; //lef!=null&&right!=null
}
}
235. 二叉搜索树的最近公共祖先==剑指68
利用bst的特性
class Solution {
// 同236
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==p||root==q||root==null) 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;
if(left==null&&right==null) return null;
return root; //lef!=null&&right!=null
}
// 利用bst的性质 迭代
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root!=null){
if(root.val>p.val&&root.val>q.val){
root=root.left;
}else if(root.val<p.val&&root.val<q.val){
root=root.right;
}else return root;
}
return null;
}
// 递归
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;
}
}
700. 二叉搜索树中的搜索
class Solution {
//递归
// public TreeNode searchBST(TreeNode root, int val) {
// if(root==null||root.val==val) return root;
// if(root.val>val) return searchBST(root.left,val);
// if(root.val<val) return searchBST(root.right,val);
// return null;
// }
//迭代
public TreeNode searchBST(TreeNode root, int val) {
while(root!=null){
if(root.val>val) root=root.left;
else if(root.val<val) root=root.right;
else return root;
}
return null;
}
}
701. 二叉搜索树中的插入操作
class Solution {
//迭代
public TreeNode insertIntoBST(TreeNode root, int val) {
TreeNode inode=new TreeNode(val);
TreeNode cur=root;//记录当前节点
if(root==null){
return inode;
}
while(true){
if(cur.val>val){
if(cur.left==null){
cur.left=inode;
return root;
}else{
cur=cur.left;
}
}else if(cur.val<val){
if(cur.right==null){
cur.right=inode;
return root;
}else{
cur=cur.right;
}
}
}
}
//递归
public TreeNode insertIntoBST(TreeNode root, int val) {
TreeNode inode=new TreeNode(val);
if(root==null){
return inode;
}
if(root.val>val)
root.left=insertIntoBST(root.left,val);
if(root.val<val)
root.right=insertIntoBST(root.right,val);
return root;
}
}
450. 删除二叉搜索树中的节点
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
// 第一种情况:没找到删除的节点,遍历到空节点直接返回了
if(root==null) return null;
if(root.val==key){
// 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
if(root.left==null&&root.right==null) return null;
// 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
if(root.left==null) return root.right;
// 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
if(root.right==null) return root.left;
// 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
else {
TreeNode cur=root.right;
while(cur.left!=null){
cur=cur.left;
}
cur.left=root.left;
TreeNode temp=root;
root=root.right;
return root;
}
}
if(root.val>key) root.left=deleteNode(root.left,key);
if(root.val<key) root.right=deleteNode(root.right,key);
return root;
}
}
669. 修剪二叉搜索树
class Solution {
//递归
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root==null) return null;
if(root.val<low){
TreeNode right=trimBST(root.right,low,high);
return right;
}
if(root.val>high){
TreeNode left=trimBST(root.left,low,high);
return left;
}
root.left=trimBST(root.left,low,high);
root.right=trimBST(root.right,low,high);
return root;
}
}
108. 将有序数组转换为二叉搜索树
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
TreeNode root=traversal(nums,0,nums.length-1);
return root;
}
public TreeNode traversal(int[] nums,int left,int right){
if(left>right) return null;
int mid=left+((right-left)/2);
TreeNode root=new TreeNode(nums[mid]);
root.left=traversal(nums,left,mid-1);
root.right=traversal(nums,mid+1,right);
return root;
}
}
538. 把二叉搜索树转换为累加树
class Solution {
int pre;
public TreeNode convertBST(TreeNode root) {
pre=0;
traversal(root);
return root;
}
// 递归
public void traversal(TreeNode cur){
if(cur==null) return;
traversal(cur.right);
cur.val+=pre;
pre=cur.val;
traversal(cur.left);
}
// 迭代
public void traversal(TreeNode root) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur=root;
while(cur!=null||stack.size()>0){
if(cur!=null){
stack.push(cur);
cur=cur.right;
}else{
cur=stack.pop();
cur.val+=pre;
pre=cur.val;
cur=cur.left;
}
}
}
}