在做这道题时,我们会想到使用递归的方法来做!
做了这么多二叉树的题,相信大家已经知道这种题的思路了!先去考虑用什么遍历方法!
那么我们就可以开始去实现了!
首先,考虑终止条件:
if (root == null) return 0;
然后我们去确定单层递归的逻辑当遇到左叶⼦节点的时候,记录数值,然后通过递归求取左⼦树左叶⼦之和,和 右⼦树左叶⼦之和,相加便是整个树的左叶⼦之和。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) return 0;
int leftNum = sumOfLeftLeaves(root.left);
if (root.left != null && root.left.left == null && root.left.right == null) {
leftNum = root.left.val;
}
int rightNum = sumOfLeftLeaves(root.right);
int sum = leftNum + rightNum;
return sum;
}
}
迭代法使⽤前中后序都是可以的,只要把左叶⼦节点统计出来,就可以了。
判断条件是一样的!
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root == null) return 0;
queue.offer(root);
int sum = 0;
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.left != null) {
if (isLeafNode(node.left)) {
sum += node.left.val;
} else {
queue.offer(node.left);
}
}
if (node.right != null) {
if (!isLeafNode(node.right)) {
queue.offer(node.right);
}
}
}
return sum;
}
public boolean isLeafNode(TreeNode node) {
return node.left == null && node.right == null;
}
}
首先,我们需要理解题目,这道题并不是求最左边的节点,而是深度最大那一层靠最左边的节点,如下图
这道题我们使用什么遍历方式都可以,因为没有中序遍历的逻辑条件!
确定终止条件
当遇到叶⼦节点的时候,就需要统计⼀下最⼤的深度了,所以需要遇到叶⼦节点来更新最⼤
深度。
if (root == null) {
return;
}
if (depth > maxDepth) {
maxDepth = depth;
result = root.val;
}
确定单层递归
depth++;
dfs(root.left, depth);
dfs(root.right, depth);
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int maxDepth = 0;
int result = 0;
public int findBottomLeftValue(TreeNode root) {
dfs(root, 0);
return result;
}
public void dfs(TreeNode root, int depth) {
if (root == null) {
return;
}
depth++;
dfs(root.left, depth);
dfs(root.right, depth);
if (depth > maxDepth) {
maxDepth = depth;
result = root.val;
}
}
}
只需要记录最后⼀⾏第⼀个节点的数值就可以了。
使用层序遍历即可!
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root == null) return 0;
queue.offer(root);
int result = 0;
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
if (cur.right != null) {
queue.offer(cur.right);
}
if (cur.left != null) {
queue.offer(cur.left);
}
result = cur.val;
}
return result;
}
}
可以使⽤深度优先遍历的⽅式(本题前中后序都可以,⽆所谓,因为中节点也没有处理逻
辑)来遍历⼆叉树。
确定终⽌条件
if (root == null) return false;
确定单层递归
如果递归函数返回true,说明找到了合适的路径,应该⽴刻返回。
if (root.left == null && root.right == null) return targetSum == root.val;
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
// 终止条件
if (root == null) return false;
if (root.left == null && root.right == null) return targetSum == root.val;
return hasPathSum(root.left, targetSum - root.val)
|| hasPathSum(root.right, targetSum - root.val);
}
}
如果使⽤栈模拟递归的话,那么如果做回溯呢?
此时栈⾥⼀个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和。
这样我们使用两个队列,分别存储将要遍历的节点,以及根节点到这些节点的路径和即可
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
Queue<TreeNode> queNode = new LinkedList<TreeNode>();
Queue<Integer> queVal = new LinkedList<Integer>();
queNode.offer(root);
queVal.offer(root.val);
while (!queNode.isEmpty()) {
TreeNode now = queNode.poll();
int temp = queVal.poll();
if (now.left == null && now.right == null) {
if (temp == sum) {
return true;
}
continue;
}
if (now.left != null) {
queNode.offer(now.left);
queVal.offer(now.left.val + temp);
}
if (now.right != null) {
queNode.offer(now.right);
queVal.offer(now.right.val + temp);
}
}
return false;
}
}
构造树⼀般采⽤的是前序遍历,因为先构造中间节点,然后递归构造左⼦树和右⼦树。
确定终止条件
题⽬中说了输⼊的数组⼤⼩⼀定是⼤于等于1的,所以我们不⽤考虑⼩于1的情况,那么当递
归遍历的时候,如果传⼊的数组⼤⼩为1,说明遍历到了叶⼦节点了。
那么应该定义⼀个新的节点,并把这个数组的数值赋给新的节点,然后返回这个节点。 这表
⽰⼀个数组⼤⼩是1的时候,构造了⼀个新的节点,并返回。
if (rightIndex - leftIndex == 1) {// 只有一个元素
return new TreeNode(nums[leftIndex]);
}
确定单层递归
int maxIndex = leftIndex;// 最大值所在位置
int maxVal = nums[maxIndex];// 最大值
for (int i = leftIndex + 1; i < rightIndex; i++) {
if (nums[i] > maxVal){
maxVal = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxVal);
public TreeNode constructMaximumBinaryTree(int[] nums) {
return constructMaximumBinaryTree1(nums, 0, nums.length);
}
public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
if (rightIndex - leftIndex < 1) {// 没有元素了
return null;
}
if (rightIndex - leftIndex == 1) {// 只有一个元素
return new TreeNode(nums[leftIndex]);
}
int maxIndex = leftIndex;// 最大值所在位置
int maxVal = nums[maxIndex];// 最大值
for (int i = leftIndex + 1; i < rightIndex; i++) {
if (nums[i] > maxVal){
maxVal = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxVal);
// 根据maxIndex划分左右子树
root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);
return root;
}