DFS,BFS应用

DFS遍历模板 

public static void dfs(TreeNode root) {
    if (root == null) {
        return;
    }
    dfs(root.left);
    dfs(root.right);

BFS遍历模板

public static void bfs(TreeNode root) {
    Queue<TreeNode> queue = new ArrayDeque<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        if (node.left != null) {
            queue.add(node.left);
        }
        if (node.right != null) {
            queue.add(node.right);
        }
    }
}

在大多数情况下我们遍历使用DFS,BFS主要使用在层序遍历和最短路径(无权)上

二叉树的前,中,后序遍历

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
    	List<Integer> list = new ArrayList<Integer>();
        preOrder(root, list);
    	return list;
    }
    //前序
    public static void preOrder(TreeNode root,List<Integer> list) {
		if (root == null) {
			return;
		}
		list.add(root.val);
		preOrder(root.left, list);
		preOrder(root.right, list);
	}
    //中序
    public static void mid(TreeNode root,List<Integer> list) {
		if (root == null) {
			return;
		}
		mid(root.left, list);
		list.add(root.val);
		mid(root.right, list);
	}
    //后序
    public static void after(TreeNode root,List<Integer> list) {
		if (root == null) {
			return;
		}
		after(root.left, list);
		after(root.right, list);
		list.add(root.val);
	}
}

二叉树的最大深度

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

    3
   / \
  9  20
    /  \
   15   7

它的最大深度为3 

//DFS
//自底向上
class Solution {
    public int maxDepth(TreeNode root) {
    	if (root == null) {
			return 0;
		}
    	int leftlen=maxDepth(root.left);
    	int rightlen=maxDepth(root.right);
    	return Math.max(leftlen, rightlen)+1;
    	
    }
}

//BFS
//自顶向下
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        int ans = 0;
        //判断当前层
        while (!queue.isEmpty()) {
            int size = queue.size();
            //将当前层的节点加入队列
            while (size > 0) {
                TreeNode node = queue.poll();
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
                size--;
            }
            //每循环一层,深度+1
            ans++;
        }
        return ans;
    }
}

对称二叉树

    1
   / \
  2   2
 / \ / \
3  4 4  3

如果是一颗对称二叉树
说明,他要么是一颗空树,要么是一颗满二叉树
而且左右子树的根节点不为空且相等,满足左子树左子节点等于右子树的右子节点,左子树的右子节点等于右子树的左子节点

class Solution {
    public boolean isSymmetric(TreeNode root) {
    	//空树必是对称
        if (root == null) {
        	return true;
        }
        return check(root.left, root.right);
    }
    public static boolean check(TreeNode left, TreeNode right) {
    	//只有一个根节点,没有子节点,对称
		if (left == null&&right == null) {
			return true;
		}
		//只有左子树或右子树为空,不对称
		if (left==null||right == null) {
			return false;
		}
		//值不相等,不对称
		if (left.val!=right.val) {
			return false;
		}
		return check(left.left, right.right)&&check(left.right, right.left);
	}
}

二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
二叉树:[3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层序遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

解题思路:

层序遍历的核心是一个队列 Queue

代码中最重要的是两个循环

while 循环控制的是层的遍历

for 循环遍历每一层所有的节点

count 获取一层元素的个数,保证 for 循环遍历的是同一层元素

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        //首先判断是否为空树
    	if (root == null) {
			return new ArrayList<>();
		}
    	Queue<TreeNode> queue = new LinkedList<>();
    	List<List<Integer>> res = new ArrayList<>();
    	//根节点入队
    	queue.add(root);
    	while(!queue.isEmpty()) {
    		//每层的节点数
    		int count=queue.size();
    		//每层的节点值
    		List<Integer> value = new ArrayList<>();
    		for (int i = 0; i < count; i++) {
    			//出队列,获取值
    			TreeNode node = queue.poll();
    			value.add(node.val);
    			if (node.left!=null) {
					queue.add(node.left);
				}
    			if (node.right != null) {
    				queue.add(node.right);
    			}
    		}
    		//将每层存储的值加入
    		res.add(value);
    	}
    	return res;
    }
}

计算二叉树每层的平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。

输入:
    3
   /  \
  9  20
      /  \
   15    7


输出:[3, 14.5, 11]
解释:
第 0 层的平均值是 3 ,  第1层是 14.5 , 第2层是 11 。因此返回 [3, 14.5, 11] 。

解题思路:

在层序遍历的基础上在每一层创建一个 double 类型的level用于计算每一层的节点值的和,最后除以每层节点的数量count 即可得到每一层的平均值,然后添加到结果集合 res中即可。

class Solution {
	public List<Double> averageOfLevels(TreeNode root) {
    	//用于存储每层的结果
    	List<Double> res = new ArrayList<>();
    	if (root==null) return res;
    	Queue<TreeNode> queue = new LinkedList<TreeNode>();
    	queue.add(root);
    	while (!queue.isEmpty()) {
    		int count=queue.size();
    		double level=0;
    		//计算每层的和
    		for (int i = 0; i < count; i++) {
    			TreeNode node = queue.poll();
    			level += node.val;
    			//添加下一层
    			if (node.left!=null) {
					queue.add(node.left);
				}
    			if (node.right != null) {
    				queue.add(node.right);
    			}
    		}
    		//计算每层的平均值
    		res.add(level/count);
    	}
    	return res;
    }
}

计算二叉树每层的最大值

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]
解释:
          1
         /  \
        3   2
       /   \   \  
      5   3   9 

解题思路:

在层序遍历的基础上在每一层创建一个 int类型的max用于计算每一层的节点值的最大值,然后添加到结果集合 res中即可。注意max的初始化为Integer.MIN_VALUE即-2147483648

class Solution {
	public List<Integer> largestValues(TreeNode root) {
    	//用于存储每层的结果
    	List<Integer> res = new ArrayList<>();
    	if (root==null) return res;
    	Queue<TreeNode> queue = new LinkedList<TreeNode>();
    	queue.add(root);
    	while (!queue.isEmpty()) {
    		int count=queue.size();
    		int max=Integer.MIN_VALUE;
    		//计算每层的最大值
    		for (int i = 0; i < count; i++) {
    			TreeNode node = queue.poll();
    			max=Math.max(max, node.val);
    			//添加下一层
    			if (node.left!=null) {
					queue.add(node.left);
				}
    			if (node.right != null) {
    				queue.add(node.right);
    			}
    		}
    		res.add(max);
    	}
    	return res;
    }
}

路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。


输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
    	if (root==null) {
			return false;
		}
    	//用于存放当前节点
    	Queue<TreeNode> node = new LinkedList<TreeNode>();
    	//用于存放当前节点的值
    	Queue<Integer> value = new LinkedList<Integer>();
    	//首先存入根节点及其值
    	node.add(root);
    	value.add(root.val);
    	while(!node.isEmpty()) {
    		TreeNode now=node.poll();
    		int temp=value.poll();
    		//找到叶子节点,判断从根节点到当前叶子节点这条路径和是否等于所给的值
    		if (now.left==null&&now.right == null) {
				if (temp==targetSum) {
					return true;
				}
				continue;
			}
    		if (now.left!=null) {
				node.add(now.left);
				value.add(now.left.val+temp);
			}
    		if (now.right != null) {
				node.add(now.right);
				value.add(now.right.val+temp);
			}
    	}
    	return false;
    }
}

BFS 遍历,层序遍历,最短路径(无权) 三者之间实际上是层层递进的关系。

在 BFS 遍历的基础上区分遍历的每一层,就得到了层序遍历。在层序遍历的基础上记录层数,就得到了最短路径。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1while(true){learn}

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值