Leetcode中二叉树中的搜索相关题目解析以及java实现
这一类的题目其实稍微有一些杂,基本就是在二叉树中寻找一些或者某个特定值,题目比较多,我们会通过两道三篇来总结,不过总体来说也基本上就是BFS,分治法就可以解决的。
让我们从简单的开始!
- [513] Find Bottom Left Tree Value
- [199] Binary Tree Right Side View
- [515] Find Largest Value in Each Tree Row
- [671] Second Minimum Node In a Binary Tree
- [116] Populating Next Right Pointers in Each Node
- [117] Populating Next Right Pointers in Each Node II
- [623] Add One Row to Tree
- [637] Average of Levels in Binary Tree
- [404] Sum of Left Leaves
Find Bottom left Tree value
这两题其实是找到二叉树中最底层的最左节点的值,遇到这种层级遍历的题目我们最先考虑的就是BFS,在BFS的过程中不断更新每一行最左节点的值,然后当BFS退出的时候这个值就是我们需要返回的结果。
class Solution {
public int findBottomLeftValue(TreeNode root) {
if(root == null)return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int res = 0;
while(!queue.isEmpty()){
int size = queue.size();
for(int i = 0;i < size;i++){
TreeNode node = queue.poll();
if(i == 0)res = node.val;
if(node.left != null)queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
}
return res;
}
}
Binary Tree Right Side View
和上一题很像,其实就是寻找二叉树中每一层最后边的节点的值,记录下来然后作为数组返回,一样是可以使用BFS的方式来解决
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> results = new ArrayList<>();
if (root == null) return results;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (i == size - 1) results.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return results;
}
}
Find Largest Value in Each Tree Row
一样也是需要层序遍历的,在BFS的过程中用一个变量来记录最大值,在每一层结束的时候将最大值存入返回数组即可。
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) return res;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size = queue.size();
int max = Integer.MIN_VALUE;
for(int i = 0; i < size;i++){
TreeNode node = queue.poll();
max = Math.max(max,node.val);
if(node.left != null)queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
res.add(max);
}
return res;
}
}
Second Minimum Node In a Binary Tree
找到二叉树中第二小的数字,这一题稍微有点特别,每一个节点要么就没有子节点,要么就一定有两个子节点,且当前节点的值不会比子节点的值大。基于这个特质,根节点肯定是第一小的值,然后我们不断遍历子数组,然后维护一个值,如果大于根节点,且比当前的值小就更新当前值。
class Solution {
public int findSecondMinimumValue(TreeNode root) {
if (root == null) return -1;
int first = root.val;
long second = Long.MAX_VALUE;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.val != first && node.val < second) second = node.val;
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
return (second == first || second == Long.MAX_VALUE) ? -1 : (int)second;
}
}
Populating Next Right Pointers in Each Node
连接完美二叉树的每一个节点的右兄弟节点。
这一道题稍微有一些特殊,二叉树的节点里面不光有左右子树,也有一个next的指针指向在右边的同级的兄弟节点。
这一题我们用递归分治法来做,先检测当前的节点是否有左子节点,如果有则把当前左子节点的next指向右边,右子节点为null也没有关系。如果当前的next不为空,就说明当前节点有兄弟节点,那么当前右子节点的next也应该指向兄弟节点的左子节点。
class Solution{
public Node connect(Node root){
if(root == null) return;
if(root.left != null){
root.left.next = root.right;
}
if(root.right != null){
root.right.next = (root.next == null)?null:root.next.left;
}
connect(root.left);
connect(root.right);
return root;
}
}
Populating Next Right Pointers in Each Node II
相比较上一题,这一题就没有完美二叉树了,存在某一个节点只有左子节点或者是只有右子节点的情况,那这种情况下用分治法就会出现问题,因为左子节点无法连接到当前兄弟节点的左子节点上,这个时候还是使用层序遍历的BFS来处理这个问题,这样每一个节点的next,肯定就是下一个在队列中的节点了。
class Solution {
public Node connect(Node root) {
if(root == null){
return null;
}
Queue<Node> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
int size = q.size();
for(int i = 0;i < size;i++){
Node node = queue.poll();
if(i < size-1){
//最后一个节点不做处理
node.next = q.peek();
}
if(node.left != null) q.offer(node.left);
if(node.right != null)q.offer(node.right);
}
}
return root;
}
}
Add One Row to Tree
这一题也是层级遍历的衍生, 输入一个根节点,一个深度和一个整型值,让我们在相对应的深度插入一行整型值的新节点,一样我们就用BFS加层数的检测,没有到的时候就正常BFS,到达我们需要的层级的时候就对队列里面的所有节点都插入两个新节点即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode addOneRow(TreeNode root, int v, int d) {
if(root == null)return null;
if(d == 1){
TreeNode newRoot = new TreeNode(v);
newRoot.left = root;
return newRoot;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
if(d-- == 0)return root;
int size = queue.size();
for(int i = 0; i < size; i++){
TreeNode node = queue.poll();
if(d == 1){
TreeNode left = new TreeNode(v);
left.left = node.left;
node.left = left;
TreeNode right = new TreeNode(v);
right.right = node.right;
node.right = right;
}else{
if(node.left != null)queue.offer(node.left);
if(node.right != null)queue.offer(node.right);
}
}
}
return root;
}
}
Average of Levels in Binary Tree
顾名思义,就是计算每一层的平均值,一样用BFS可以轻松解决
List<Double> results = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
long sum = 0;
int count = 0;
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
sum += node.val;
count++;
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
results.add((double) sum / count);
}
return results;
Sum of Left Leaves
统计所有左叶子节点的和,一样我们可以用BFS来处理,当每一层中出现一个左子节点的时候就加入到返回值中。
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null || root.left == null && root.right == null)return 0;
int sum = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
if(node.left != null && node.left.left == null && node.left.right == null) sum+= node.left.val;
if(node.left != null) queue.offer(node.left);
if(node.right != null)queue.offer(node.right);
}
return sum;
}
}
今天的题目基本上都是可以用BFS来解决的搜索和统计问题,还是非常简单的。