今天继续打卡,进行二叉树相关题目的学习
#本期思路分享偏少,题目难度适中,希望辩证地分析笔者给出的参考代码,仅供参考
目录
- 题目1、110.平衡二叉树
- 题目2、257. 二叉树的所有路径
- 题目3、404.左叶子之和
题目1、110.平衡二叉树
后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树_哔哩哔哩_bilibili
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
示例 1:
给定二叉树 [3,9,20,null,null,15,7]
返回 true 。
C(仅供参考)
#include <stdio.h>
#include <stdlib.h>
#include <math.h> // 为了 max 函数,但这里我们可以直接使用条件表达式
// 定义 TreeNode 结构体
typedef struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
// 获取树的高度,如果不平衡则返回 -1
int getHeight(TreeNode* node) {
if (node == NULL) {
return 0;
}
int leftHeight = getHeight(node->left);
if (leftHeight == -1) return -1; // 左子树不平衡
int rightHeight = getHeight(node->right);
if (rightHeight == -1) return -1; // 右子树不平衡
// 如果左右子树高度差大于 1,则不平衡
if (abs(leftHeight - rightHeight) > 1) {
return -1;
}
// 返回当前节点的高度(即左右子树中较大的高度 + 1)
return 1 + (leftHeight > rightHeight ? leftHeight : rightHeight);
}
// 检查树是否平衡
bool isBalanced(TreeNode* root) {
// 如果树为空,则认为是平衡的
if (root == NULL) {
return true;
}
// 如果树的高度为 -1,则表示不平衡
return getHeight(root) != -1;
}
python(仅供参考)
#因为python没有TreeNode的显式定义,所以使用一个类来定义
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def getHeight(node):
if not node:
return 0
leftHeight = getHeight(node.left)
if leftHeight == -1:
return -1
rightHeight = getHeight(node.right)
if rightHeight == -1:
return -1
if abs(leftHeight - rightHeight) > 1:
return -1
return 1 + max(leftHeight, rightHeight)
def isBalanced(root):
return getHeight(root) != -1
题目2.257. 二叉树的所有路径
递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径_哔哩哔哩_bilibili
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
C#(来自代码随想录)
public IList<string> BinaryTreePaths(TreeNode root)
{
List<int> path = new();
List<string> res = new();
if (root == null) return res;
Traversal(root, path, res);
return res;
}
public void Traversal(TreeNode node, List<int> path, List<string> res)
{
path.Add(node.val);
if (node.left == null && node.right == null)
{
string sPath = "";
for (int i = 0; i < path.Count - 1; i++)
{
sPath += path[i].ToString();
sPath += "->";
}
sPath += path[path.Count - 1].ToString();
res.Add(sPath);
return;
}
if (node.left != null)
{
Traversal(node.left, path, res);
path.RemoveAt(path.Count-1);
}
if (node.right != null)
{
Traversal(node.right, path, res);
path.RemoveAt(path.Count-1);
}
}
python(仅供参考)
# Definition for a binary tree node.
class Solution:
def traversal(self, cur, path, result):
path.append(cur.val) # 中
if not cur.left and not cur.right: # 到达叶子节点
sPath = '->'.join(map(str, path))
result.append(sPath)
return
if cur.left: # 左
self.traversal(cur.left, path, result)
path.pop() # 回溯
if cur.right: # 右
self.traversal(cur.right, path, result)
path.pop() # 回溯
def binaryTreePaths(self, root):
result = []
path = []
if not root:
return result
self.traversal(root, path, result)
return result
我们先定义一个包含traversal方法
和binaryTreePaths方法的类,
这两个方法共同用于找出给定二叉树的所有从根节点到叶子节点的路径,并以字符串列表的形式返回这些路径。每条路径上的节点值通过“->”连接。
方法解析
traversal(self, cur, path, result)
- 参数:
cur
:当前遍历到的节点。path
:一个列表,用于存储从根节点到当前节点的路径上的所有节点值。result
:一个列表,用于存储所有从根节点到叶子节点的路径(以字符串形式)。
- 逻辑:
- 首先,将当前节点的值
cur.val
添加到path
列表中。 - 检查当前节点是否为叶子节点,如果是叶节点则将
path
列表中的节点值通过“->”连接成一个字符串,并添加到result
列表中, 然后返回, 因为已经到达叶子节点,不需要再进一步遍历。 - 如果当前节点有左子节点,则递归调用
traversal
方法遍历左子树,并在遍历完左子树后,通过path.pop()
将当前节点从path
中移除(回溯),以便后续可能遍历右子树时不会包含当前节点的值。 - 类似地,如果当前节点有右子节点,则递归调用
traversal
方法遍历右子树,并在遍历完右子树后进行回溯。
- 首先,将当前节点的值
binaryTreePaths(self, root)
- 逻辑:
- 初始化两个空列表:
result
用于存储最终的结果(即所有路径),path
用于在遍历过程中存储当前路径。 - 检查根节点是否为空。如果为空,则直接返回空的
result
列表,因为没有路径可以返回。 - 调用
traversal
方法开始遍历树,传入根节点、空的path
列表和空的result
列表作为参数。 - 遍历完成后,
result
列表中将包含所有从根节点到叶子节点的路径(以字符串形式),返回这个列表。
- 初始化两个空列表:
题目3.404.左叶子之和
二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和 (opens new window)
计算给定二叉树的所有左叶子之和。
示例:
C(仅供参考)
int getSumOfLeftLeaves(struct TreeNode* node, int* sum) {
if (node == NULL) {
return 0;
}
// 检查当前节点是否是左叶子节点
if (node->left == NULL && node->right == NULL && node->val != 0 && (node->parent == NULL || node->parent->left == node)) {
// 注意:原问题没有提到parent指针,这里只是为了演示如何检查是否为左子树的叶子。
// 在实际情况下,你可能需要其他方式来确定节点是否位于左子树。
// 由于这里没有parent指针,我们假设所有叶子都是可接受的(简化版)
// 但为了更精确地解决问题,你应该只添加左子树中叶子节点的值
// 这里我们假设所有叶子都是左子树的叶子(为了简化)
*sum += node->val;
}
// 递归遍历左子树和右子树
getSumOfLeftLeaves(node->left, sum);
getSumOfLeftLeaves(node->right, sum);
return 0; // 返回值在这里并不重要,因为我们使用sum参数来传递结果
}
// 主函数,用于计算左叶子节点的和
int sumOfLeftLeaves(struct TreeNode* root) {
int sum = 0;
getSumOfLeftLeaves(root, &sum);
return sum;
}
困难:代码放到leetcode老是报错,debug半天发现不了编译错误,头都要大了。难道我是天生报错圣体?