110.平衡二叉树
讲解链接:代码随想录-110.平衡二叉树
这里求的是高度,所以使用后序遍历。节点获取左右子节点的最大高度,然后相减的差绝对值大于 1,就说明不是平衡二叉树了。
解题代码:
public boolean isBalanced(TreeNode root) {
return getHeight(root) != -1;
}
private int getHeight(TreeNode root) {
if (root == null) {
return 0;
}
int leftHeight = getHeight(root.left);
if (leftHeight == -1) {
return -1;
}
int rightHeight = getHeight(root.right);
if (rightHeight == -1) {
return -1;
}
// 左右子树高度差大于1,return -1表示已经不是平衡树了
if (Math.abs(leftHeight - rightHeight) > 1) {
return -1;
}
return Math.max(leftHeight, rightHeight) + 1;
}
257.二叉树的所有路径
讲解链接:代码随想录-257.二叉树的所有路径
使用前序遍历,
- 确定递归方法参数和返回值:参数需要传入父级的路径,同时还有一个结果集。
- 确定递归终止条件:当节点是叶子节点的时候,就可以返回了。把父级路径加上自己,添加到结果集中就可以了。
- 确定单层递归逻辑:这里需要用到回溯,针对参数父级的路径,如果不回溯的话,节点的左子节点路径遍历完了,不是会继续添加右子节点路径,结果就错误了。
解题代码:
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
if (root == null) return result;
List<Integer> paths = new ArrayList<>();
traversal(root, paths, result);
return result;
}
void traversal(TreeNode node, List<Integer> paths, List<String> result) {
paths.add(node.val);
if (node.left == null && node.right == null) {
StringBuilder tempPath = new StringBuilder();
for (int i = 0; i < paths.size(); i++) {
tempPath.append(paths.get(i));
if (i != paths.size() - 1) {
tempPath.append("->");
}
}
result.add(tempPath.toString());
return;
}
if (node.left != null) {
traversal(node.left, paths, result);
paths.remove(paths.size() - 1);
}
if (node.right != null) {
traversal(node.right, paths, result);
paths.remove(paths.size() - 1);
}
}
404.左叶子之和
讲解链接:代码随想录-404.左叶子之和
递归两种思路,
- 在叶子结点的父节点就判断子节点是否是坐叶子结点,如果是就返回左叶子结点的值,否则返回 0。
- 还有一个是递归入参多加一个参数,用来告诉子节点自己是不是左子节点,如果是叶子结点同时也是左子节点,那么就返回节点值。
递归法
父节点收集
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
int leftValue = sumOfLeftLeaves(root.left); // 左
int rightValue = sumOfLeftLeaves(root.right); // 右
int midValue = 0;
if (root.left != null && root.left.left == null && root.left.right == null) {
midValue = root.left.val;
}
int sum = midValue + leftValue + rightValue; // 中
return sum;
}
子节点判断返回
public int sumOfLeftLeaves(TreeNode root) {
return traversal(root, false);
}
int traversal(TreeNode node, boolean left) {
if (node == null) {
return 0;
}
// 如果是叶子节点,同时是左子节点,返回节点值
if (node.left == null && node.right == null && left) {
return node.val;
}
int sum = 0;
sum += traversal(node.left, true);
sum += traversal(node.right, false);
return sum;
}
迭代法
前序遍历
这里用的迭代方式前序遍历,思路和迭代法第一种一样,判断子节点是否是叶子结点,是的话就加上。
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
Stack<TreeNode> stack = new Stack<> ();
stack.add(root);
int result = 0;
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (node.left != null && node.left.left == null && node.left.right == null) {
result += node.left.val;
}
if (node.right != null) stack.add(node.right);
if (node.left != null) stack.add(node.left);
}
return result;
}
层序遍历
父节点判断
public int sumOfLeftLeaves(TreeNode root) {
int sum = 0;
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
while (size-- > 0) {
TreeNode node = queue.poll();
if (node.left != null) { // 左节点不为空
queue.offer(node.left);
if (node.left.left == null && node.left.right == null) { // 左叶子节点
sum += node.left.val;
}
}
if (node.right != null) queue.offer(node.right);
}
}
return sum;
}