代码随想录算法训练营Day14|二叉树part02

87 阅读4分钟

LeetCode 226 翻转二叉树

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

文档讲解:programmercarl.com/0226.翻转二叉树.…

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

思路

反转每个节点的左右子节点。 考虑层序遍历,当每个节点被处理的时候,反转它的左右子节点,再把非空子节点入队。 且本题不需要区分不同的层,所以无需记录每层的节点数量,只要队列不为空,就可以医治循环处理节点。 考虑递归遍历,前后序遍历都是可以的,但中序遍历不方便实现,因为会把某一子树重复反转。

  1. 确定递归函数的参数和返回值: 参数:树根节点 返回值:空
  2. 确定结束条件:根节点为空或叶子节点可以返回
  3. 确定单层递归逻辑:反转左右子节点,再分别对左右子节点递归调用

解法(层序遍历)

class Solution {
	public TreeNode invertTree(TreeNode root) {	
		Queue<TreeNode> queue = new LinkedList<>();		
		if (root != null) {		
			queue.offer(root);		
		}		
		while (!queue.isEmpty()) {		
			TreeNode node = queue.poll();			
			// 交换左右子节点			
			TreeNode tmp = node.left;			
			node.left = node.right;			
			node.right = tmp;			
			// 左右子节点入队			
			if (node.left != null) {			
				queue.offer(node.left);			
			}			
			if (node.right != null) {			
				queue.offer(node.right);			
			}		
		}		
		return root;	
	}
}

解法(前序遍历)

class Solution {
	public TreeNode invertTree(TreeNode root) {	
		traverse(root);		
		return root;	
	}		  
	
	public void traverse(TreeNode root) {	
		if (root == null || (root.left == null && root.right == null)) {		
			return ;		
		}		
		TreeNode tmp = root.left;		
		root.left = root.right;		
		root.right = tmp;		
		traverse(root.left);		
		traverse(root.right);	
	}
}

LeetCode 101 对称二叉树

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

文档讲解:programmercarl.com/0101.对称二叉树.…

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

思路

考虑对称二叉树的结构,可以发现根节点的左右子树是镜像的。也就是说,如果对左子树用左中右的顺序遍历,而右子树用右中左的顺序遍历,得到的结果应该是一样的。 所以我们可以如下设计一个递归函数:

  1. 递归函数的参数和返回值: 参数:左子树的根节点root1和右子树的根节点root2 返回值:布尔类型
  2. 递归结束条件:
    1. 当root1和root2均为空,返回true
    2. 如果有一个root为空而另一个非空,返回false
    3. 比较root1和root2值,不相等则返回false
  3. 单层递归逻辑:
    1. 递归对root1.left和root2.right调用👉flag1
    2. 递归对root1.right和root2.left调用👉flag2
    3. 返回flag1且flag2

解法

class Solution {
	public boolean isSymmetric(TreeNode root) {	
		return traverse(root.left, root.right);	
	}	
	  	
	public boolean traverse(TreeNode root1, TreeNode root2) {	
		if (root1 == null) {		
			if (root2 == null) {			
				return true;			
			}			
			else {			
				return false;			
			}		
		}		
		else {			
			if (root2 == null) {			
				return false;			
			}			
			else if (root1.val != root2.val) {			
				return false;			
			}		
		}		
		boolean flag1 = traverse(root1.left, root2.right);		
		boolean flag2 = traverse(root1.right, root2.left);		
		return flag1 & flag2;	
	}
}

LeetCode 104 二叉树的最大深度(递归法)

层序遍历中使用过层序遍历法,这次用递归法

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

文档讲解:programmercarl.com/0104.二叉树的最大…

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

思路

首先需要一个全局变量depth标识遍历时的深度,每次进入递归函数depth+1,要退出时就depth-1。 其次需要一个全局变量maxDepth记录遍历过程中最大的深度,最后在主函数中返回。初始化为0,方便对于空树输入直接返回0.

考虑递归函数三要素:

  1. 递归函数的参数和返回值 参数:根节点 返回值:空
  2. 递归函数的结束条件 根节点为空,立即返回
  3. 单层递归逻辑:
    1. depth+1后和maxDepth比较,更新maxDepth
    2. 分别对根节点的左子节点和右子节点递归调用
    3. depth-1

解法

class Solution {
	int depth;	
	int maxDepth;	
	public int maxDepth(TreeNode root) {		
		depth = 0;		
		maxDepth = 0;		
		traverse(root);		
		return maxDepth;	
	}		  
	
	public void traverse(TreeNode root) {	
		if (root == null) {		
			return ;		
		}		
		depth++;		
		maxDepth = Math.max(depth, maxDepth);		
		traverse(root.left);		
		traverse(root.right);		
		depth--;	
	}
}

LeetCode 111 二叉树的最小深度(递归法)

层序遍历中使用过层序遍历法,这次用递归法

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

文档讲解:programmercarl.com/0111.二叉树的最小…

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

思路

首先需要一个全局变量depth标识遍历时的深度,每次进入递归函数depth+1,要退出时就depth-1。

其次需要一个全局变量minDepth记录遍历过程中叶子节点的最小深度,最后在主函数中返回。

考虑递归函数三要素:

  1. 递归函数的参数和返回值 参数:根节点 返回值:空
  2. 递归函数的结束条件 根节点为空,立即返回
  3. 单层递归逻辑:
    1. depth+1
    2. 如果节点是叶子节点,把depth和minDepth比较,更新minDepth
    3. 分别对根节点的左子节点和右子节点递归调用
    4. depth-1

解法

class Solution {
	int depth;	
	int minDepth;	
	public int minDepth(TreeNode root) {	
		if (root == null) {		
			return 0;		
		}		
		depth = 0;		
		minDepth = Integer.MAX_VALUE;		
		traverse(root);		
		return minDepth;	
	}		  
	
	public void traverse(TreeNode root) {	
		if (root == null) {		
			return ;		
		}		
		depth++;		
		if (root.left == null && root.right == null) {		
			minDepth = Math.min(depth, minDepth);		
		}		
		traverse(root.left);		
		traverse(root.right);		
		depth--;	
	}
}

今日收获总结

今日学习3小时,用递归法重做了一些题目。在写递归函数之前搞清楚递归三要素非常重要,可以减少bug的出现,也能捋清楚递归的过程