代码随想录算法训练营Day18|二叉树part06

111 阅读4分钟

LeetCode 530 二叉搜索树的最小绝对差

题目链接:leetcode.cn/problems/mi…

文档讲解:programmercarl.com/0530.二叉搜索树的…

视频讲解:https://www.bilibili.com/video/BV1DD4y11779

思路

中序遍历二叉搜索树,是单调递增序列。最小绝对差一定出现在中序遍历中相邻的节点之间。

考虑递归三要素:

  1. 递归函数的参数和返回值 全局变量:前序节点prev,最小绝对差minDiff 参数:根节点 返回值:空
  2. 递归函数的结束条件 当节点为空,返回
  3. 单层递归逻辑 对左子节点递归调用 如果prev为空,把root置为prev,返回 如果prev不为空,计算root与prev的绝对差,更新最小绝对差,把root置为prev 对右子节点递归调用

解法

class Solution {
	int minDiff;	
	TreeNode prev;	
	
	public int getMinimumDifference(TreeNode root) {	
		prev = null;		
		minDiff = Integer.MAX_VALUE;		
		traverse(root);		
		return minDiff;	
	}		  
	
	public void traverse(TreeNode root) {	
		if (root == null) {			
			return ;		
		}		
		traverse(root.left);		
		if (prev != null) {		
			int diff = Math.abs(prev.val - root.val);			
			minDiff = Math.min(minDiff, diff);		
		}		
		prev = root;		
		traverse(root.right);		
		return ;	
	}
}

LeetCode 501 二叉搜索树中的众数

题目链接:leetcode.cn/problems/fi…

文档讲解:programmercarl.com/0501.二叉搜索树中…

视频讲解:www.bilibili.com/video/BV1fD…

思路

有重复值的二叉搜索树中序遍历非递减,相同的数都相邻。故中序遍历搜索树,记录下次数最多的数即可。但一个数最终出现多少次,需要在其最后一个相同的数出现后才能判断。所以在主函数中,还需要处理最后一个遍历的节点所更新的次数信息。

由于众数可能不止一个,但是同为众数的值出现次数相同。所以当次数等于众数次数时,可以直接加入数组;如果大雨众数次数,需要丢弃之前的数,只放入当前值。

考虑递归三要素:

  1. 递归函数的参数和返回值 全局变量:众数mode数组,众数出现的次数maxNum,前序节点prev,前序节点次数prevNum 参数:根节点 返回值:空
  2. 递归函数的结束条件 根节点为空,返回
  3. 单层递归的逻辑 对左子节点递归调用 如果prev不为空,且prev与root值相等,prevNum+1 如果prev不为空,且两者不等,更新众数。prevNum重置为1 如果prev为空,prevNum置为1 把prev置为root 对右子节点递归调用 返回

解法

class Solution {	
	List<Integer> result;	
	int maxNum;	
	TreeNode prev;	
	int prevNum;	
	public int[] findMode(TreeNode root) {	
		result = new ArrayList<>();		
		prev = null;		
		prevNum = 0;		
		maxNum = 0;		
		traverse(root);		
		if (prevNum == maxNum) {		
			result.add(prev.val);		
		}		
		else if (prevNum > maxNum) {		
			result = new ArrayList<>();			
			result.add(prev.val);		
		}		
		return result.stream().mapToInt(Integer::intValue).toArray();	
	}	
	  	
	public void traverse(TreeNode root) {	
		if (root == null) {		
			return ;		
		}		
		traverse(root.left);		
		if (prev != null) {		
			if (prev.val == root.val) {			
				prevNum++;			
			}			
			else {			
				if (prevNum == maxNum) {				
					result.add(prev.val);				
				}			
				else if (prevNum > maxNum) {				
					maxNum = prevNum;					
					result = new ArrayList<>();					
					result.add(prev.val);				
				}			
				prevNum = 1;			
			}		
		}		
		else {		
			prevNum = 1;		
		}		
		prev = root;		
		traverse(root.right);	
	}
}

LeetCode 236 二叉树的最近公共祖先

题目链接:leetcode.cn/problems/lo…

文档讲解:programmercarl.com/0236.二叉树的最近…

视频讲解:www.bilibili.com/video/BV1jd…

思路

最近公共祖先与节点p和q的关系可分为以下两种:

  1. 祖先是p或q:此时p存在于q的某子树中,或q存在于p的某子树中
  2. 祖先不是p或q:此时p和q一定分别存在于祖先的左右子树中。

所以我们要寻找的公共祖先节点有以下特征:

  1. 等于p或q,且q或p在其子树中
  2. p和q分别存在于其左右子树中

节点的特征取决于子树,所以使用后序遍历。此外由于树中每个节点的值都不同,只要确定是p或q的一个就可以了,因为不会重复。

考虑递归三要素:

  1. 递归函数的参数和返回值 全局变量:最近公共祖先result 参数:根节点root 返回值:布尔值,标识树中有无p或q
  2. 递归函数的结束条件 根节点为空,返回false
  3. 单层递归逻辑 对左子节点递归调用👉flag1 对右子节点递归调用👉flag2 如果两个flag都为真,result置为根节点,返回true 如果一个为真一个为假且root为p或q,result置为根节点,返回true 如果全为假且root为p或q,返回true 否则返回false

解法

class Solution {
	int p;	
	int q;	
	TreeNode result;	
	public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {	
		this.p = p.val;	
		this.q = q.val;	
		traverse(root);	
		return result;	
	}		  
	
	public boolean traverse(TreeNode root) {
		if (root == null) {		
			return false;		
		}		
		boolean flag1 = traverse(root.left);		
		boolean flag2 = traverse(root.right);		
		if (flag1 && flag2) {		
			result = root;			
			return true;		
		}		
		if (flag1 || flag2) {		
			if (root.val == p || root.val == q) {			
				result = root;				
				System.out.println(result.val);			
			}			
			return true;		
		}		
		if (root.val == p || root.val == q) {		
			return true;		
		}		
		return false;	
	}
}

今日收获总结

今日学习两小时,if-else条件判断时,同层的判断尽量互斥,不容易出bug