开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情 这也是第42篇文章
前言
在上两篇文章讲搜索算法时,也提到过搜索在图和树中的应用。所以这篇文章再来谈谈树这个数据结构。
但是树太多了,这篇文章中我们先以二叉树作为研究对象,谈谈它的构造过程和一些经典问题。
递归构造树的三种方式
树可以分为三大部分:根节点,左子树,右子树。遍历的顺序形成了三种不同的构造方式。
前序遍历(preoder)
指的是先访问根节点,再分别访问左右子树。这种算法和深度优先搜索有点像。
注意事项:递归结束条件(后续不再提醒)
class Solution {
List<Integer> list=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
preorder(root);
return list;
}
public void preorder(TreeNode root){
if(root==null) return ;
list.add(root.val);
preorder(root.left);
preorder(root.right);
}
}
中序遍历
和前序遍历类似,只需要把list.add(root.val);夹到两段递归代码中间,然后把递归函数preorder的名字也改一下就行了。
class Solution {
List<Integer> list=new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
inorder(root);
return list;
}
public void inorder(TreeNode root){
if(root==null) return ;
inorder(root.left);
list.add(root.val);
inorder(root.right);
}
}
后序遍历
相信大家都已经懂套路了,我就只放最关键的代码了:
postorder(root.left);
postorder(root.right);
list.add(root.val);
二叉树最大深度
思路
这个问题也可以通过递归遍历左右子树解决。而所谓“最大”,可理解为选取左子树和右子树中深度较大者。
代码实现
class Solution {
public int maxDepth(TreeNode root) {
return dfs(root,0);
}
public int dfs(TreeNode root,int depth){
if(root==null) return depth;
depth++;
int left=dfs(root.left,depth);
int right=dfs(root.right,depth);
return Math.max(left,right);
}
}
求根节点到叶节点数字之和
是“计算叶子结点个数”一题的升级版。
思路
也是递归遍历左右子树,会用到前缀和的思想,也就是:
int pre=val*10+root.val;
来达到题目要求的“数字的和”的要求。
代码实现
class Solution {
public int sumNumbers(TreeNode root) {
return dfs(root,0);
}
public int dfs(TreeNode root,int val){
if(root==null) return 0;
int pre=val*10+root.val;
if(root.left==null&&root.right==null) return pre;
return dfs(root.left,pre)+dfs(root.right,pre);
}
}