目录
平衡二叉树(Leetcode110)
思路
1、先计算左右子树的深度
2、判断左右子树深度的差
3、如果差>1则返回-1 小于1则返回最大的深度
public boolean isBalanced(TreeNode root) {
if(dfs(root)==-1) {
return false;
}else {
return true;
}
}
public int dfs(TreeNode root) {
if(root==null) {
return 0;
}
int left = dfs(root.left);
if(left == -1) {
return -1;
}
int right = dfs(root.right);
if(right == -1) {
return -1;
}
int result;
if(Math.abs(left-right)>1) { //只要一个地方出现了-1 不论怎么减都是-1
return -1;
}else {
result = Math.max(right, left)+1;
}
return result;
}
二叉树的所有路径(Leetcode257)
思路
1、前序遍历 遍历到中节点时对左右两边进行判断看是不是叶子节点
2、如果是叶子节点,则从list中循环取出值,以样例模版进行格式化,并加上当前的值,因为list保存的是之前的路径
注意:list保存的是上一个节点的值,result保存的是一个路径,注意每次递归完成后要回溯
public static List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
List<Integer> list = new ArrayList<>();
if(root.left==null&&root.right==null) {
result.add(new String(""+root.val));
return result;
}
else if(root!=null) {
dfs(root,list,result);
}
return result;
}
public static void dfs(TreeNode root,List<Integer> list,List<String> result) {
if(root.left==null&&root.right==null) {
StringBuilder temp = new StringBuilder();
for(int i = 0;i<list.size();i++) {
temp.append(list.get(i));
temp.append("->");
}
temp.append(root.val);
result.add(new String(temp));
}
if(root.left!=null) {
list.add(root.val);
dfs(root.left,list,result);
list.remove(list.size()-1);
}
if(root.right!=null) {
list.add(root.val);
dfs(root.right,list,result);
list.remove(list.size()-1);
}
}
左叶子节点之和(Leetcode404)
思路:也是遍历,不过要判断是是当前节点的下左节点是不是叶子节点,如果是则加上
static int cnt;
public int sumOfLeftLeaves(TreeNode root) {
cnt = 0;
if(root==null) {
return 0;
}else {
dfs(root);
}
return cnt;
}
public void dfs(TreeNode root) {
if(root.left!=null&&root.left.left==null&&root.left.right==null) {
cnt+=root.left.val; //判断是不是左叶子节点
}
if(root.left!=null) {
dfs(root.left);
}
if(root.right!=null) {
dfs(root.right);
}
}
找树左下角的值(Leetcode513)
思路:层序遍历,最后一层的第一个值就是答案
public int findBottomLeftValue(TreeNode root) {
Deque<TreeNode> de = new LinkedList<>();
if(root==null) {
return root.val;
}
de.add(root);
int result = root.val;
while(!de.isEmpty()) {
int size = de.size();
for(int i = 0;i<size;i++) {
TreeNode temp = de.pollFirst();
if(i==0) {
result = temp.val;
}
if(temp.left!=null) {
de.add(temp.left);
}
if(temp.right!=null) {
de.add(temp.right);
}
}
}
return result;
}
路径总和(Leetcode112)
思路 直接用一个参数记录当前经过路径值的和即可,到叶子节点时进行判断,如果是直接flag==1,退出
递归
static int flag;
public boolean hasPathSum(TreeNode root, int targetSum) {
flag = 0;
dfs(root,0,targetSum);
if(root==null) {
return false;
}
if(flag==1) {
return true;
}
return false;
}
public void dfs(TreeNode root,int sum,int targetSum) {
if(flag==1) {
return;
}
if(root.left==null&&root.right==null) {
if(sum+root.val==targetSum) {
flag=1;
}
return;
}
if(root.left!=null) {
dfs(root.left,sum+root.val,targetSum);
}
if(root.right!=null) {
dfs(root.right,sum+root.val,targetSum);
}
}
路径总和2(Leetcode113)
思路:也是递归记录每条路径的值,要注意的是,符合条件的时候要新开一个temp来存list的值,然后再存入result里面,这样就不会报错
static List<List<Integer>> result;
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
result = new ArrayList<>();
List<Integer> list = new ArrayList<>();
if(root==null) {
return result;
}else {
travel(root,targetSum,0,list);
}
return result;
}
public void travel(TreeNode root, int targetSum,int sum,List<Integer> list) {
if(root.left==null&&root.right==null) {
if(sum+root.val==targetSum) {
List<Integer> temp = new ArrayList<>();
for(int i = 0;i<list.size();i++) {
temp.add(list.get(i));
}
temp.add(root.val);
result.add(temp);
}
return;
}
if(root.left!=null) {
list.add(root.val);
travel(root.left,targetSum,sum+root.val,list);
list.remove((list.size()-1));
}
if(root.right!=null) {
list.add(root.val);
travel(root.right,targetSum,sum+root.val,list);
list.remove((list.size()-1));
}
}
从中序和后续遍历序列构造二叉树(Leetcode106)
思路:
1、先获取后序数组的最后一个值为根值
2、查询中序序列中根值所在位置,方便切分左右数组
3、根据步骤2确定的值来对中序数组和后序数组进行切分
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(postorder.length == 0 || inorder.length == 0)
return null;
return dfs(inorder, 0, inorder.length, postorder, 0, postorder.length);
}
public TreeNode dfs(int[] inorder,int beginL,int endL,int[] postorder,int beginP,int endP) {
if(beginP==endP) {
return null;
}
int rootVal = postorder[endP-1]; //这里不能是postorder.length-1 不然每次递归的值都一样
TreeNode root = new TreeNode(rootVal);
int len;
for(len=0;len<inorder.length;len++) {
if(inorder[len]==rootVal) {
break;
}
}
int inorderLeftStart = beginL;
int inorderLeftEnd = len;
int inorderRightStart = len+1;
int inorderRightEnd = endL;
int postorderLeftStart = beginP;
int postorderLeftEnd = beginP+(len-beginL); //+len会报错 要+的应该是len-beginL(截取的数量数)
int postorderRightStart = postorderLeftEnd;
int postorderRightEnd = endP-1;
root.left = dfs(inorder,inorderLeftStart,inorderLeftEnd,postorder,postorderLeftStart,postorderLeftEnd);
root.right = dfs(inorder,inorderRightStart,inorderRightEnd,postorder,postorderRightStart,postorderRightEnd);
return root;
}
从前序和中序遍历序列构造二叉树(Leetcode105)
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length==0||inorder.length==0) {
return null;
}
return dfs(preorder,0,preorder.length,inorder,0,inorder.length);
}
public TreeNode dfs(int[] preorder,int p_start,int p_end,int[] inorder,int i_start,int i_end) {
if(p_start==p_end) {
return null;
}
int rootVal = preorder[p_start];
TreeNode root = new TreeNode(rootVal);
int len = 0;
for(len=0;len<inorder.length;len++) {
if(rootVal==inorder[len]) {
break;
}
}
int i_l_s = i_start;
int i_l_e = len;
int i_r_s = len+1;
int i_r_e = i_end;
int p_l_s = p_start+1;
int p_l_e = p_start+1+(len-i_start);
int p_r_s = p_l_e;
int p_r_e = p_end;
root.left=dfs(preorder,p_l_s,p_l_e,inorder,i_l_s,i_l_e);
root.right=dfs(preorder,p_r_s,p_r_e,inorder,i_r_s,i_r_e);
return root;
}
最大二叉树(Leetcode654)
1、先找到数组最大的值为根结点
2、递归划分左子树和右子树
public TreeNode constructMaximumBinaryTree(int[] nums) {
return dfs(nums,0,nums.length);
}
public TreeNode dfs(int[] nums,int start,int end) {
if(nums==null) {
return null;
}
if(start==end) { //节点为空
return null;
}
int flag = Integer.MIN_VALUE;
int len = 0;
for(int i = start;i<end;i++) {
if(flag<nums[i]) {
len = i; //找到最大值下标
flag = nums[i]; //找到最大值
}
}
TreeNode root = new TreeNode(flag); //构造为根节点
int left_start = start; //左子树
int left_end = len;
int right_start = len+1;//右子树
int right_end = end;
root.left = dfs(nums,left_start,left_end);
root.right = dfs(nums,right_start,right_end);
return root;
}
合并二叉树(Leetcode617)
思路:
1、如果都为空则返回null。
2、两个树同时遍历,如果其中一个为null,返回另一个树的节点即可。
3、不是以上的情况就是重合了,相加成新节点返回
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return dfs(root1,root2);
}
public TreeNode dfs(TreeNode root1,TreeNode root2) {
if(root1==null&&root2==null) {
return null;
}
if(root1==null) {
return root2;
}
if(root2==null) {
return root1;
}
int val = root1.val+root2.val;
TreeNode root = new TreeNode(val);
root.left = dfs(root1.left,root2.left);
root.right = dfs(root1.right,root2.right);
return root;
}
二叉搜索树中的搜索(Leetcode700)
思路
1、找到值相同的节点返回
2、二叉搜索树有顺序的左小于右
3、如果当前节点值大于val我们遍历左节点,如果小于val我们遍历右节点
public TreeNode searchBST(TreeNode root, int val) {
return dfs(root,val);
}
public TreeNode dfs(TreeNode root,int val) {
if(root==null||root.val==val) {
return root;
}
TreeNode result =null;
if(root.val>val){
result = dfs(root.left,val);
}
if(root.val<val) {
result = dfs(root.right,val);
}
return result;
}
验证二叉搜索树(Leetcode98)
思路 由中序遍历出来的二叉搜索树是有序的
static TreeNode result = null;
public TreeNode searchBST(TreeNode root, int val) {
dfs(root,val);
return result;
}
public void dfs(TreeNode root,int val) {
if(root==null) {
return;
}
if(root.val==val) {
result = root;
return;
}
dfs(root.left,val);
dfs(root.right,val);
}
二叉搜索树的最小绝对值(Leetcode530)
思路1、用中序遍历出来序列 然后两个比对即可
static List<Integer> list;
public int getMinimumDifference(TreeNode root) {
list = new LinkedList<>();
dfs(root);
int result = Integer.MAX_VALUE;
for(int i = 1;i<list.size();i++) {
result = Math.min(result, list.get(i)-list.get(i-1));
}
return result;
}
public void dfs(TreeNode root) {
if(root==null) {
return;
}
dfs(root.left);
list.add(root.val);
dfs(root.right);
}
思路2 每次用一个中间节点来记录当前值的前一个节点
class Solution {
static int result;
static TreeNode pre;
public int getMinimumDifference(TreeNode root) {
pre = null; //这一步不能少,不然pre.val默认为-1,会报错
result = Integer.MAX_VALUE;
dfs(root);
return result;
}
public void dfs(TreeNode root) {
if(root==null){
return;
}
dfs(root.left);
if(pre!=null){
result = Math.min(Math.abs(root.val-pre.val),result);
}
pre = root;
dfs(root.right);
}
}
二叉树中的众数(Leetcode501)
思路:每次遍历的时候用map记录频率,然后再对map进行排序即可
class Solution {
public static Map<Integer,Integer>map;
public int[] findMode(TreeNode root) {
map = new HashMap<>();
dfs(root);
Set entrySet = map.entrySet();
List<Map.Entry<Integer,Integer>> list = new LinkedList<>(entrySet);
list.sort(new Comparator<Map.Entry<Integer,Integer>>(){
@Override
public int compare(Map.Entry<Integer,Integer> o1,Map.Entry<Integer,Integer> o2){
return o2.getValue()-o1.getValue();
}
});
List result = new LinkedList<>();
result.add(list.get(0).getKey());
for(int i = 1;i<list.size();i++){
if(map.get(list.get(i).getKey())== map.get(list.get(0).getKey())){
result.add(list.get(i).getKey());
}
}
int[] arr = new int[result.size()];
for(int i = 0;i<arr.length;i++){
arr[i] = (int)result.get(i);
}
return arr;
}
public void dfs(TreeNode root){
if(root==null){
return;
}
dfs(root.left);
map.put(root.val,map.getOrDefault(root.val,0)+1);
dfs(root.right);
}
}
二叉树的最小公共祖先(Leetcode236)
思路:从下到上判断,用到了后序遍历的回溯
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return dfs(root,p,q);
}
public TreeNode dfs(TreeNode root,TreeNode p,TreeNode q){
if(root==null||root==p||root==q){
return root;
}
TreeNode left = dfs(root.left,p,q);
TreeNode right = dfs(root.right,p,q);
if(left!=null&&right!=null){
return root;
}
if(left!=null&&right==null){
return left;
}else if(left==null&&right!=null){
return right;
}else{
return null;
}
}
}
二叉搜索树中的插入操作(Leetcode701)
按照二叉搜索树有序的性质去遍历,直到找到空结点++
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
dfs(root,val);
return root;
}
public TreeNode dfs(TreeNode root,int val){
if(root==null){
TreeNode temp = new TreeNode(val);
return temp;
}
if(root.val>val){
root.left = dfs(root.left,val);
}
if(root.val<val){
root.right = dfs(root.right,val);
}
return root;
}
}
删除二叉搜索树中的节点(Leetcode450)
思路:遍历返回节点 分情况返回
情况1:如果左节点为空,返回这个节点的右节点
情况2:如果右节点为空,返回这个节点的左节点
情况3:左右都不空,则把左节点挂在右节点的左叶子节点上,然后返回右节点
class Solution {
static TreeNode pre;
public TreeNode deleteNode(TreeNode root, int key) {
return dfs(root,key);
}
public TreeNode dfs(TreeNode root,int key){
if(root==null){
return root;
}
if(root.val==key){
if(root.left==null){
return root.right;
}else if (root.right==null){
return root.left;
}else{
TreeNode cur = root.right;
while(cur.left!=null){
cur = cur.left;
}
cur.left = root.left;
root = root.right;
return root;
}
}
if(root.val>key) root.left = dfs(root.left,key);
if(root.val<key) root.right = dfs(root.right,key);
return root;
}
}
修剪二叉搜索树(Leetcode669)
思路:1、遇见空返回空
2、遇见比最小范围小的 则遍历这个节点的右边
3、遇见比最大范围大的则遍历这个节点的左边
4、符合的直接继续遍历返回即可
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
return dfs(root,low,high);
}
public TreeNode dfs(TreeNode root,int low,int high){
if(root==null){
return null;
}
if(root.val<low){
TreeNode left = dfs(root.right,low,high);
return left;
}
if(root.val>high){
TreeNode right = dfs(root.left,low,high);
return right;
}
root.left = dfs(root.left,low,high);
root.right = dfs(root.right,low,high);
return root;
}
}
将有序数组转换成二叉搜索树(Leetcode108)
思路:由于有序所以每次找到当前数组的中间值构建节点就可以了,然后每次以中间索引进行数组的划分
划分为左右子树
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return dfs(nums,0,nums.length);
}
public TreeNode dfs(int[] nums,int l ,int r){
if(r-l<1){
return null;
}
int mid = (l+r)/2;
TreeNode root = new TreeNode(nums[mid]);
root.left = dfs(nums,l,mid);
root.right = dfs(nums,mid+1,r);
return root;
}
}
把二叉搜索树转换成累加树(Leetcode538)
思路:可以发现二叉搜索树按中序遍历出来是有序的,然后累加就是全部值的和减去前n个节点的值
1:先算出总节点的和
2:中序遍历,总节点要减去前几个节点的值,然后赋值给当前节点。
class Solution {
static int count = 0;
static int temp;
public TreeNode convertBST(TreeNode root) {
count = dfs_Val(root);
pre = new TreeNode(0);
dfs(root);
return root;
}
public void dfs(TreeNode root){
if(root==null){
return;
}
dfs(root.left);
temp = root.val;
root.val = count;
count =count-temp; //减去前一个节点的值得到当前得count
dfs(root.right);
}
public int dfs_Val(TreeNode root){
if(root==null){
return 0;
}
return dfs_Val(root.left)+dfs_Val(root.right)+root.val;
}