513.找树左下角的值
使用层序遍历,该题则是遍历到最后一层时第一个存入的值便为树左下角的值
这是自己思考后写出的代码:
class Solution {
public int findBottomLeftValue(TreeNode root) {
if (root.left == null && root.right == null)
return root.val;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
int res = 0;
while (!q.isEmpty()) {
int sz = q.size();
for (int i = 0; i < sz; i++) {
TreeNode cur = q.poll();
if (cur.left != null) {
q.offer(cur.left);
}
if (cur.right != null) {
q.offer(cur.right);
}
}
// 此时记录下一层第一个元素
TreeNode nxt = q.peek();
// 如果为空则说明为最后一层
if (nxt == null) {
break;
}
if (nxt.left == null && nxt.right == null) {
res = nxt.val;
}
}
return res;
}
}
而如若使用【递归】解决
由于二叉树递归遍历是先遍历左子树,再遍历右子树,所以到最大深度时第一次遇见的节点便是树的左下角的节点
代码如下:
class Solution {
// 记录二叉树的最大深度
int maxDepth = 0;
// 记录 traverse 递归遍历到的深度
int depth = 0;
TreeNode res = null;
public int findBottomLeftValue(TreeNode root) {
traverse(root);
return res.val;
}
void traverse(TreeNode root) {
if (root == null) {
return;
}
// 前序遍历位置
depth++;
if (depth > maxDepth) {
// 到最大深度时第一次遇到的节点就是左下角的节点
maxDepth = depth;
res = root;
}
if(root.left != null){
traverse(root.left);
}
if(root.right != null){
traverse(root.right);
}
// 后序遍历位置
depth--;
}
}
112.路径总和
这道题很简单,无非就是遍历二叉树的时候将路径值进行相加,进行判断
代码如下:
class Solution {
/* 解法一、分解问题的思路 */
// 定义:输入一个根节点,返回该根节点到叶子节点是否存在一条和为 targetSum 的路径
public boolean hasPathSum(TreeNode root, int targetSum) {
// base case
if (root == null) {
return false;
}
if (root.left == root.right && root.val == targetSum) {
return true;
}
return hasPathSum(root.left, targetSum - root.val)
|| hasPathSum(root.right, targetSum - root.val);
}
/* 解法二、遍历二叉树的思路 */
int target;
boolean found = false;
// 记录遍历过程中的路径和
int curSum = 0;
public boolean hasPathSum_2(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
this.target = targetSum;
traverse(root);
return found;
}
// 二叉树遍历函数
void traverse(TreeNode root) {
if (root == null) {
return;
}
// 前序遍历位置
curSum += root.val;
if (root.left == null && root.right == null) {
if (curSum == target) {
found = true;
}
}
traverse(root.left);
traverse(root.right);
// 后序遍历位置
curSum -= root.val;
}
}
113.路径总和II
该题目在112的基础上改变了返回值,该题目需要返回的是路径,则将符合题解的路径存入即可
代码如下:
class Solution {
int sum = 0;
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if(root == null) return res;
backtrack(root,targetSum);
return res;
}
public void backtrack(TreeNode root,int targetSum) {
if(root == null) return;
sum += root.val;
track.add(root.val);
if(root.left == null && root.right == null){
if(sum == targetSum){
res.add(new LinkedList<>(track));
}
}
backtrack(root.left,targetSum);
backtrack(root.right,targetSum);
track.removeLast();
sum -= root.val;
}
}
105.从前序与中序遍历序列构造二叉树
首先明确前序遍历 与 中序遍历的数组元素分布特点
找到根节点是很简单的,前序遍历的第一个值 preorder[0]
就是根节点的值。
关键在于如何通过根节点的值,将 preorder
和 inorder
数组划分成两半,构造根节点的左右子树?
所以就需要利用中序遍历确定二叉树的左右子树部分
对于 preorder
数组情况
所以代码如下:
class Solution {
// 存储 inorder 中值到索引的映射
HashMap<Integer,Integer> valToIndex = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i = 0;i < inorder.length; i++){
valToIndex.put(inorder[i], i);
}
return build(preorder,0,preorder.length - 1,
inorder,0,inorder.length - 1);
}
public TreeNode build(int[] preorder, int preStart, int preEnd,
int[] inorder, int inStart, int inEnd){
// 判断给出的先序遍历结果是否合理
if(preStart > preEnd){
return null;
}
// root 节点对应的值就是前序遍历数组的第一个元素
int rootVal = preorder[preStart];
// rootVal 在中序遍历数组中的索引
int index = valToIndex.get(rootVal);
int leftSize = index - inStart;
// 先构造出当前根节点
TreeNode root = new TreeNode(rootVal);
// 递归构造左右子树
root.left = build(preorder,preStart + 1,preStart + leftSize,
inorder,inStart,index - 1);
root.right = build(preorder,preStart + leftSize + 1,preEnd,
inorder,index + 1,inEnd);
return root;
}
}
106.从中序与后序遍历序列构造二叉树
思路与105一致
数组索引变为:
代码如下:
class Solution {
// 存储 inorder 中值到索引的映射
HashMap<Integer, Integer> valToIndex = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
for (int i = 0; i < inorder.length; i++) {
valToIndex.put(inorder[i], i);
}
return build(inorder, 0, inorder.length - 1,
postorder, 0, postorder.length - 1);
}
/*
定义:
中序遍历数组为 inorder[inStart..inEnd],
后序遍历数组为 postorder[postStart..postEnd],
构造这个二叉树并返回该二叉树的根节点
*/
TreeNode build(int[] inorder, int inStart, int inEnd,
int[] postorder, int postStart, int postEnd) {
if (inStart > inEnd) {
return null;
}
// root 节点对应的值就是后序遍历数组的最后一个元素
int rootVal = postorder[postEnd];
// rootVal 在中序遍历数组中的索引
int index = valToIndex.get(rootVal);
// 左子树的节点个数
int leftSize = index - inStart;
TreeNode root = new TreeNode(rootVal);
// 递归构造左右子树
root.left = build(inorder, inStart, index - 1,
postorder, postStart, postStart + leftSize - 1);
root.right = build(inorder, index + 1, inEnd,
postorder, postStart + leftSize, postEnd - 1);
return root;
}
}