参考:
数据结构——二叉树先序、中序、后序及层次四种遍历(C语言版)_正弦定理的博客-CSDN博客_二叉树的先序,中序,后序遍历c语言
二叉树问题的解决。所有方法如下【基本上可以解决相关所有的问题】
1. 递归【DFS】2. 队列【BFS】
1. 二叉树遍历
前序:小人跑步
中序:阳光投影
后序:剪葡萄
前序:
@Data
class TreeNode{
private Integer val;
public TreeNode left;
public TreeNode right;
public TreeNode(Integer val){
this.val = val;
}
public TreeNode(int val, TreeNode left, TreeNode right){
this.val = val;
this.right = right;
this.left = left;
}
}
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
TreeNode treeNode = new TreeNode(1, new TreeNode(2), null);
List<Integer> integers = solution.preOrderTree(treeNode);
for (Integer integer : integers) {
System.out.println(integer);
}
}
public List<Integer> preOrderTree(TreeNode root){
List<Integer> res = new ArrayList<>();
preOrder(res, root);
return res;
}
public void preOrder(List<Integer> res, TreeNode root){
if (root == null){
return;
}
res.add(root.getVal());
preOrder(res, root.left);
preOrder(res, root.right);
}
}
中序:
public void inOrder(List<Integer> res, TreeNode root){
if (root == null){
return;
}
inOrder(res, root.left);
res.add(root.getVal());
inOrder(res, root.right);
}
后序:
public void postOrder(List<Integer> res, TreeNode root){
if (root == null){
return;
}
postOrder(res, root.left);
postOrder(res, root.right);
res.add(root.getVal());
}
2. 反转二叉树【二叉树的镜像】
翻转一棵二叉树。
额外分析:如此做法的时间复杂度和空间复杂度分别是多少呢?
时间复杂度:因为每一个结点都进行了左右孩子交换。所以O(N)
空间复杂度:每一层都进行了递归。而递归是嵌套的。所以只需要计算层数就好 LogN
示例:
输入:
4 / \ 2 7 / \ / \ 1 3 6 9
输出:
4 / \ 7 2 / \ / \ 9 6 3 1
public class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
TreeNode treeNode = new TreeNode(1, new TreeNode(2), null);
solution.reverseTree(treeNode);
System.out.println(treeNode.right.val);
}
public void reverseTree(TreeNode root){
if (root == null){
return;
}
TreeNode tmp = root.right;
root.right = root.left;
root.left = tmp;
reverseTree(root.left);
reverseTree(root.right);
}
}
3. 层序遍历二叉树
首先看看深度优先和广度优先
DFS:
void dfs(TreeNode root) { if (root == null) { return; } dfs(root.left); dfs(root.right); }
BFS:【尤为适合解决层序遍历和最短路径】
void bfs(TreeNode root) { Queue<TreeNode> queue = new ArrayDeque<>(); queue.add(root); while (!queue.isEmpty()) { TreeNode node = queue.poll(); // Java 的 pop 写作 poll() if (node.left != null) { queue.add(node.left); } if (node.right != null) { queue.add(node.right); } } }
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]]
public List<List<Integer>> Bfs(TreeNode root){
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> treeNodeQueue = new ArrayDeque<>();
if (root != null){
treeNodeQueue.add(root);
}
while (treeNodeQueue.isEmpty()){
List<Integer> mid = new ArrayList<>();
int n = treeNodeQueue.size();
for (int i = 0; i < n; i++) {
TreeNode poll = treeNodeQueue.poll();
mid.add(poll.getVal());
if (poll.getLeft() != null){
treeNodeQueue.add(poll.getLeft());
}
if (poll.getRight() != null){
treeNodeQueue.add(poll.getRight());
}
}
res.add(mid);
}
return res;
}
4. 地图分析【BFS】
你现在手里有一份大小为 N x N 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
如果网格上只有陆地或者海洋,请返回 -1。
示例 1:
输入:[[1,0,1],[0,0,0],[1,0,1]] 输出:2 解释: 海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2。
对于图的BFS也是一样滴~ 与Tree的BFS区别如下:
1、tree只有1个root,而图可以有多个源点,所以首先需要把多个源点都入队。
2、tree是有向的因此不需要标志是否访问过,而对于无向图来说,必须得标志是否访问过!
并且为了防止某个节点多次入队,需要在入队之前就将其设置成已访问!
public int maxDistance(int[][] array){
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
int m = array.length;
int n = array[0].length;
Queue<int[]> queue = new ArrayDeque<>();
//先把所有的陆地进行入队
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
if (array[i][j] == 1){
queue.add(new int[]{i, j});
}
}
}
int[] point = null;
boolean hasOcean = false;
//一圈一圈的进行遍历。最终的结果就是最大队列【因为步数最多啊】
while (!queue.isEmpty()){
point = queue.poll();
int curr_X = point[0];
int curr_y = point[1];
for (int i=0; i<4; i++){
int new_X = curr_X + dx[i];
int new_Y = curr_y + dy[i];
if (new_X <0 || new_X >=n || new_Y<0 || new_Y>=m || array[new_X][new_Y] != 0){
continue;
}
array[new_X][new_Y] = array[curr_X][curr_y] + 1;
hasOcean = true;
queue.add(new int[]{new_X, new_Y});
}
}
if (point == null || !hasOcean){
return -1;
}
return array[point[0]][point[1]] -1;
}
5. 二叉树的深度【DFS】
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) {
return 0;
} else {
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}
}
}