513.找树左下角的值
题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/
文档讲解:https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html
视频讲解:https://www.bilibili.com/video/BV1424y1Z7pn
思路
- 层序迭代遍历的代码比较简单。
- 递归法中三个遍历顺序都可以。因为是找最后一层最左的结点,只要先遍历左节点就可以。
代码
层序遍历
class Solution {
public int findBottomLeftValue(TreeNode root) {
int res = 0;
if (root == null) return 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
int flag = 0;
while (size-- > 0) {
flag++;
TreeNode node = deque.pollFirst();
if (flag == 1) res = node.val;
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
}
}
return res;
}
}
递归
class Solution {
int maxDepth = Integer.MIN_VALUE;
int res;
public int findBottomLeftValue(TreeNode root) {
if (root == null) return 0;
getBottom(root, 1);
return res;
}
public void getBottom(TreeNode root, int depth){
if (root.left == null && root.right == null) {
if (depth > maxDepth) {
maxDepth = depth;
res = root.val;
}
}
if (root.left != null) { // 左
getBottom(root.left, depth + 1); // 隐藏回溯
}
if (root.right != null) { // 右
getBottom(root.right, depth + 1);
}
// 本题没有中
}
}
112. 路径总和
题目链接:https://leetcode.cn/problems/path-sum/
文档讲解:https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频讲解:https://www.bilibili.com/video/BV19t4y1L7CR
思路
本题也是没有对中结点的处理所以前中后序遍历都可以。
代码
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
return getHasPathSum(root, targetSum - root.val); // 这里传入的是减去当前节点的值
}
public boolean getHasPathSum(TreeNode root, int count) {
if (root.left == null && root.right == null && count == 0) return true;
if (root.left != null) {
if (getHasPathSum(root.left, count - root.left.val)) return true;
}
if (root.right != null) {
if (getHasPathSum(root.right, count - root.right.val)) return true;
}
return false;
}
}
113.路径总和ii
代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if (root == null) return res;
path.add(root.val);
getPath(root, targetSum - root.val);
return res;
}
public void getPath(TreeNode root, int count) {
if (root.left == null && root.right == null && count == 0) {
res.add(new ArrayList<>(path)); // 使用了 new ArrayList<>(path) 来创建一个 path 的副本。这是因为 path 是一个全局变量,如果直接添加 path 的引用,那么在后续的操作中,任何对 path 的修改都会影响到结果列表中的路径。
return;
}// 找到合适的路径,返回
if (root.left == null && root.right == null) return; // 到叶子结点但数值不对,返回
if (root.left != null) {
path.add(root.left.val);
getPath(root.left, count - root.left.val);
path.remove(path.size() - 1);
}
if (root.right != null) {
path.add(root.right.val);
getPath(root.right, count - root.right.val);
path.remove(path.size() - 1);
}
return;
}
}
106.从中序与后序遍历序列构造二叉树
题目链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
文档讲解:https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频讲解:https://www.bilibili.com/video/BV1vW4y1i7dn
思路
- 后序数组为0,空节点;数组长度为1,直接返回根节点。
- 后序数组最后一个元素为节点元素。
- 寻找中序数组位置作切割点。
- 切中序数组(根据中节点切)。
- 切后序数组(根据中序数组切出来的左子树长度来切)。
- 递归处理左区间右区间。
- 注意统一区间左闭右闭或者左闭右开。
代码
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
//1.数组大小为0,空节点
if (inorder.length == 0) return null;
return traversal(inorder, postorder);
}
public TreeNode traversal(int[] inorder, int[] postorder) {
//1.数组大小为0,空节点
if (inorder.length == 0 || postorder.length == 0) return null;
// 2.如果不为空,取后序最后一个作为根节点(中节点)
int rootValue = postorder[inorder.length - 1];
TreeNode root = new TreeNode(rootValue);
// 3.找到rootValue在中序数组中的位置,作为切割点
int index;
for (index = 0; index < inorder.length; index++) {
if (inorder[index] == rootValue) break;
}
// 4.切割中序数组,切割成左中序和右中序
int[] leftInorder = new int[index];
int[] rightInorder = new int[inorder.length - index - 1];
for (int i = 0, j = 0; i < inorder.length; i++) {
if (i < index) leftInorder[i] = inorder[i];
else if (i == index) continue;
else rightInorder[j++] = inorder[i];
}
// 5.切割后序数组,切割成左后序和右后序
int[] leftPostorder = new int[leftInorder.length];
int[] rightPostorder = new int[rightInorder.length];
for (int i = 0; i < leftInorder.length; i++) {
leftPostorder[i] = postorder[i];
}
for (int i = 0; i < rightInorder.length; i++) {
rightPostorder[i] = postorder[i + index];
}
// 6.递归处理左区间和右区间
root.left = traversal(leftInorder, leftPostorder);
root.right = traversal(rightInorder, rightPostorder);
return root;
}
}
105.从前序与中序遍历序列构造二叉树
题目链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/
代码
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0) return null;
return getTree(preorder, inorder);
}
public TreeNode getTree(int[] preorder, int[] inorder) {
// 1. 后序数组为0,空节点;数组长度为1,直接返回根节点。
if (inorder.length == 0 || preorder.length == 0) return null;
// 2. 前序数组第一个元素为节点元素。
int rootValue = preorder[0];
TreeNode root = new TreeNode(rootValue);
if (inorder.length == 1) return root;
// 3. 寻找中序数组位置作切割点。
int index;
for (index = 0; index < inorder.length; index++) {
if (inorder[index] == rootValue) break;
}
// 4. 切中序数组,切成左中序和右中序
int[] leftInorder = new int[index];
int[] rightInorder = new int[inorder.length - index - 1];
for (int i = 0, j = 0; i < inorder.length; i++) {
if (i < index) leftInorder[i] = inorder[i];
else if (i == index) continue;
else rightInorder[j++] = inorder[i];
}
// 5.切前序数组,切成左前序和右前序
int[] leftPreorder = new int[leftInorder.length];
int[] rightPreorder = new int[rightInorder.length];
for (int i = 1, j = 0; i < preorder.length; i++) {
if (i < 1 + leftInorder.length) leftPreorder[i - 1] = preorder[i];
else rightPreorder[j++] = preorder[i];
}
// 6. 递归处理左区间右区间
root.left = getTree(leftPreorder, leftInorder);
root.right = getTree(rightPreorder, rightInorder);
return root;
}
}
之前准备面试落下好几天的任务,这两天的博客就简单写了,具体思路注释在代码里。