题目:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/
思路:前序遍历:根左右
代码:
递归:
public List preorderTraversal(TreeNode root) {List res = new ArrayList<>();preorder(root, res);return res;}public void preorder(TreeNode root, List res) {if (root == null) return;res.add(root.val);preorder(root.left, res);preorder(root.right, res);}
非递归:
public List preorderTraversal(TreeNode root) {Stack st = new Stack<>();List res = new ArrayList<>();if (root != null) st.push(root);while (!st.isEmpty()) {TreeNode node = st.pop();res.add(node.val);if (node.right != null) st.push(node.right);if (node.left != null) st.push(node.left);}return res;}
题目:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
链接:https://leetcode.cn/problems/binary-tree-inorder-traversal/
思路:中序:左根右
非递归
代码:
public List inorderTraversal(TreeNode root) {List res = new ArrayList<>();Stack st = new Stack<>();while (root != null || !st.isEmpty()) {// 根节点不为空,根节点入栈,继续往左走if (root != null) {st.push(root);root = root.left;}else {// 根节点为空,栈不为空,出栈访问,继续往右走root = st.pop();res.add(root.val);root = root.right;}}return res;}
题目:给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
链接:https://leetcode.cn/problems/binary-tree-postorder-traversal/
思路:后序:左右根
前序:根左右 —> 改为根右左 —> 再反转
反转:Collections.reverse(res);
代码:
public List postorderTraversal(TreeNode root) {List res = new ArrayList<>();Stack st = new Stack<>();// 前序:根左右 ---> 根右左if (root != null) st.push(root);while (!st.isEmpty()) {TreeNode node = st.pop();res.add(node.val);if (node.left != null) st.push(node.left);if (node.right != null) st.push(node.right);}// 反转 根右左 ---> 左右根Collections.reverse(res);return res;}
题目:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)
链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/
思路:层次遍历:队列
代码:
public List> levelOrder(TreeNode root) {List> res = new ArrayList<>();Queue q = new ArrayDeque<>();// 1. 处理根节点if (root != null) q.add(root);// 2.遍历每层while (!q.isEmpty()) {int n = q.size(); // 记录当层节点数List level = new ArrayList<>(); // 记录当层节点值// 处理当层节点:1.出栈并访问 2.左节点入队 3.右节点入队 for (int i = 0; i < n; i ++) {TreeNode node = q.poll();level.add(node.val);if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}res.add(level);}return res;}
题目:自底向上的层序遍历
链接:https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/
思路:层次遍历,最后反转结果
代码:
public List> levelOrderBottom(TreeNode root) {List> res = new ArrayList<>();Queue q = new ArrayDeque<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();List level = new ArrayList<>();for (int i = 0; i < n; i ++) {TreeNode node = q.poll();level.add(node.val);if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}res.add(level);}// 反转Collections.reverse(res);return res;}
题目:给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
链接:https://leetcode.cn/problems/binary-tree-right-side-view/
思路:层次遍历,记录每层的最后一个节点值
代码:
public List rightSideView(TreeNode root) {List res = new ArrayList<>();Queue q = new ArrayDeque<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();for (int i = 0; i < n; i ++) {TreeNode node = q.poll();// res记录每层的最后一个节点if (i == n - 1) res.add(node.val);if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}}return res;}
题目:给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
链接:https://leetcode.cn/problems/average-of-levels-in-binary-tree/
思路:层次遍历,每层遍历时,求得节点的sum,一层遍历完成后取平均
代码:
public List averageOfLevels(TreeNode root) {List res = new ArrayList<>();Queue q = new ArrayDeque<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size(); double sum = 0; // 每层节点求和List level = new ArrayList<>(); for (int i = 0; i < n; i ++) {TreeNode node = q.poll();sum += node.val;if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}// 节点值和去平均后放入resres.add(sum / n);}return res;}
题目:给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔
链接:https://leetcode.cn/problems/n-ary-tree-level-order-traversal/
思路:层次遍历
代码:
public List> levelOrder(Node root) {List> res = new ArrayList<>();Queue q = new ArrayDeque<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();List level = new ArrayList<>();for (int i = 0; i < n; i ++) {Node node = q.poll();level.add(node.val);// N叉树 遍历入队List children = node.children;for (Node child : children) {if (child != null) q.add(child);}}res.add(level);}return res;}
题目:给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值
链接:https://leetcode.cn/problems/find-largest-value-in-each-tree-row/
思路:层次遍历
代码:
public List largestValues(TreeNode root) {List res = new ArrayList<>();Queue q = new ArrayDeque<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size(), max = Integer.MIN_VALUE;for (int i = 0; i < n; i ++) {TreeNode node = q.poll();max = Math.max(max, node.val);if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}res.add(max);}return res;}
题目:给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点
struct Node {int val;Node *left;Node *right;Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL
链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/
思路:层次遍历
LinkedList,处理本层第一个节点、非第一个节点、最后一个节点方法不同
代码:
只能使用常量级额外空间
思路简单,但不满足题目条件
public Node connect(Node root) {LinkedList q = new LinkedList<>();if (root == null) return root;q.add(root);while(!q.isEmpty()) {int n = q.size();// 将队列中的元素串联起来Node node = q.get(0);for (int i = 1; i < n; i ++) {node.next = q.get(i);node = q.get(i);}// 遍历每个节点并入队for (int i = 0; i < n; i ++) {node = q.remove();if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}}return root;}
public Node connect(Node root) {Queue q = new LinkedList<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();Node node = null;Node nodePre = null;for (int i = 0; i < n; i ++) {// 本层第一个节点if (i == 0) {node = q.poll();nodePre = node;} else {// 本层非第一个节点node = q.poll();nodePre.next = node;nodePre = nodePre.next;}if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}// 本层最后一个节点nodePre.next = null;}return root;}
题目:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点。
链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/
思路:
层次遍历
递归
代码:
层次遍历:
public int maxDepth(TreeNode root) {int depth= 0;Queue q = new LinkedList<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();for (int i = 0; i < n; i ++) {TreeNode node = q.poll();if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}depth ++;}return depth;}
递归:
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;}}
题目:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点
链接:https://leetcode.cn/problems/minimum-depth-of-binary-tree/
思路:层次遍历:当遍历到左右孩子都为空时,说明到达最低点
代码:
递归:
public int minDepth(TreeNode root) {if (root == null) return 0;// 注意是根节点到叶子节点// 比如:如果根节点没有左子树,有右子树,最小深度不为1if (root.left != null && root.right == null) {return 1 + minDepth(root.left);}if (root.left == null && root.right != null) {return 1 + minDepth(root.right);}return 1 + Math.min(minDepth(root.left), minDepth(root.right));}
层次遍历:
public int minDepth(TreeNode root) {int depth = 0;Queue q = new LinkedList<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();depth ++;for (int i = 0; i < n; i ++) {root = q.poll();// 当左右孩子都为空时,说明遍历到最低点if (root.left == null && root.right == null) {return depth;}if (root.left != null) q.add(root.left);if (root.right != null) q.add(root.right);}}return depth;}
题目:给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔
链接:https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/
思路:类似于二叉树的最大深度
1.递归法
2.迭代法(层次遍历)
代码:
递归
public int maxDepth(Node root) {int depth = 0;if (root == null) return depth;for (Node child : root.children){depth = Math.max(depth, maxDepth(child));}return depth + 1;}
层次遍历
public int maxDepth(Node root) {int depth = 0;Queue q = new LinkedList<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();depth ++;for (int i = 0; i < n; i ++) {Node node = q.poll();for (Node child : node.children) {if (child != null) q.add(child);}}}return depth;}
题目:给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
链接:https://leetcode.cn/problems/invert-binary-tree/
思路:遍历时翻转每个节点的左右子节点,前序、后序、层次都可以,中序要注意避免左右节点翻转两次
代码:层次
public TreeNode invertTree(TreeNode root) {Queue q = new LinkedList<>();if (root != null) q.add(root);while (!q.isEmpty()) {int n = q.size();for (int i = 0; i < n; i ++) {TreeNode node = q.poll();swap(node);if (node.left != null) q.add(node.left);if (node.right != null) q.add(node.right);}}return root;}public void swap(TreeNode node) {TreeNode tmp = node.left;node.left = node.right;node.right = tmp;}
题目:给你一个二叉树的根节点 root , 检查它是否轴对称。
链接:https://leetcode.cn/problems/symmetric-tree/
思路
递归:判断节点为空、不为空的情况;不为空时判断节点值是否相同
注意比较对象:
1.左子树的左节点<=>右子树的右节点
2.左子树的右节点<=>右子树的左节点
代码:
递归
public boolean isSymmetric(TreeNode root) {if (root == null) return true;return compare(root.left, root.right);}boolean compare(TreeNode left, TreeNode right) {// 判断节点为空的情况if (left == null && right != null) return false;else if (left != null && right == null) return false;else if (left == null && right == null) return true;// 判断节点不为空的情况else if (left.val != right.val) return false;// 节点不为空,且节点值相等,递归遍历else return compare(left.left, right.right) && compare(left.right, right.left);}
迭代:
public boolean isSymmetric(TreeNode root) {Queue q = new LinkedList<>();if (root == null) return true;q.add(root.left);q.add(root.right);while (!q.isEmpty()) {TreeNode leftNode = q.poll(), rightNode = q.poll();if (leftNode == null && rightNode == null) continue;// false情况合集if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) return false;q.add(leftNode.left);q.add(rightNode.right);q.add(leftNode.right);q.add(rightNode.left);}return true;}
未完待续…