上一篇博客讲到二叉树的三种遍历方式,在实际中我们用的最多 最好理解的还是前序遍历,所以我们今天所有的题都是以前序遍历为基础展开的。
求结点个数:
//计算结点个数
static int size = 0;
public void getSize1(Node root) {
if(root == null) {
return;
}
size ++;
getSize1(root.left);
getSize1(root.right);
}
// 子问题思路-求结点个数
public int getSize2(Node root) {
if(root == null) {
return 0;
}
int count = 1;
count += getSize2(root.left);
count += getSize2(root.right);
return count;
}
//子问题思路-求结点个数
public int getSize3(Node root) {
if(root == null) {
return 0;
}
return 1 + getSize3(root.left) + getSize3(root.right);
}
主要思想就是利用前序遍历(若不懂前序遍历看上一篇博客),只要这个结点不为空就对这个结点进行访问(此题访问方式遍历计数器size ++),对于第二第三个优化就是减少空间消耗方便逐步理解。
求叶子结点个数:
//求叶子结点个数
static int leafSize = 0;
public void getLeafSize1(Node root) {
if(root == null) {
return;
}
if(root.left == null && root.right == null) {
leafSize ++;
}
getLeafSize1(root.left);
getLeafSize1(root.right);
}
// 子问题思路-求叶子结点个数
public int getLeafSize2(Node root) {
if(root == null) {
return 0;
}
int count = 0;
if(root.left == null && root.right == null) {
count ++;
}
count += getLeafSize2(root.left);
count += getLeafSize2(root.right);
return count;
}
// 子问题思路-求叶子结点个数
public int getLeafSize3(Node root) {
if(root == null) {
return 0;
}
if(root.left == null && root.right == null) {
return 1;
}
return getLeafSize3(root.left) + getLeafSize3(root.right);
}
运用前序遍历挨个访问树中的结点,此时对结点的访问方式就是对其进行判断,若他的左结点和右结点都为空(为叶子结点),我们将计数器++。持续优化还是减少了空间的消耗方便理解。
第k层结点个数:
// 子问题思路-求第 k 层结点个数
public int getKLevelSize(Node root, int k) {
if(root == null) {
return 0;
}
if(k < 1) {
return 0;
}
if(k == 1) {
return 1;
}
int count = 0;
count += getKLevelSize(root.left, k - 1);
count += getKLevelSize(root.right, k -1);
return count;
}
运用前序遍历,注意k的合法范围,该题的解决点在于找第k层,只要k不为1我们就找该结点的子节点的k - 1层,持续递归直到找到k为1那层的结点,就表明第k层有这个结点,所以返回1,返回上一个方法count计数器+ 1 。可想而知这道题还可以优化,写成这样主要为了方便理解。
找val结点:
// 查找 val 所在结点,没有找到返回 null
// 按照 根 -> 左子树 -> 右子树的顺序进行查找
// 一旦找到,立即返回,不需要继续在其他位置查找
public Node find(Node root, char val) {
if(root == null) {
return null;
}
if(root.val == val) {
return root;
}
Node node = find(root.left, val);
if(node != null) {
return node;
}
return find(root.right, val);
}
这道题其实不是很难,主要就是题中要求一旦找到就立即返回不需要继续寻找,所以我们在每一次使用完一次递归都对返回的结点进行一次判空操作,只要不为空,就表明我们已经找到该结点,直接return返回。