代码随想录(二叉树)

目录

平衡二叉树(Leetcode110)

二叉树的所有路径(Leetcode257)

左叶子节点之和(Leetcode404)

找树左下角的值(Leetcode513)

路径总和(Leetcode112)

路径总和2(Leetcode113)

从中序和后续遍历序列构造二叉树(Leetcode106)

从前序和中序遍历序列构造二叉树(Leetcode105)

最大二叉树(Leetcode654)

合并二叉树(Leetcode617) 

二叉搜索树中的搜索(Leetcode700)

验证二叉搜索树(Leetcode98)

二叉搜索树的最小绝对值(Leetcode530)

二叉树中的众数(Leetcode501)

二叉树的最小公共祖先(Leetcode236)

二叉搜索树中的插入操作(Leetcode701)

删除二叉搜索树中的节点(Leetcode450)

 修剪二叉搜索树(Leetcode669)

将有序数组转换成二叉搜索树(Leetcode108)

把二叉搜索树转换成累加树(Leetcode538)


平衡二叉树(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;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值