Leetcode C++ 二叉树&递归
Leetecode 104
104. Maximum Depth of Binary Tree
Given the root of a binary tree, return its maximum depth.
A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
- 思路:
递归方法求解。
int maxDepth(TreeNode* root) {
if (!root)
return 0;
return 1 + max(maxDepth(root->left), maxDepth(root->right));
}
Leetecode 111
111. Minimum Depth of Binary Tree
Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
Note: A leaf is a node with no children.
- 思路:
递归方法求解。与leetcode104(求最大深度)相比较需要注意的是当一个节点一边子树为空而另一边子树存在时,为空的子树将不参加计算,而只需要返回另一个非空子树的最小深度。
int minDepth(TreeNode* root) {
if (!root)
return 0;
if (root->left && root->right) // 左右子树都存在
return 1 + min(minDepth(root->left), minDepth(root->right));
if (root->left) // 右子树为空,左子树存在
return 1 + minDepth(root->left);
else if (root->right) // 右子树存在,左子树为空
return 1 + minDepth(root->right);
else // 左右子树都为空
return 1;
}
第二种实现
int minDepth(TreeNode* root) {
if (!root)
return 0;
int l_depth = INT_MAX; // 当左右子树只有一个为空时,其深度将定义为最大值
int r_depth = INT_MAX;
if (!root->left && !root->right) // 终止条件
return 1;
if (root->left)
l_depth = minDepth(root->left);
if (root->right)
r_depth = minDepth(root->right);
return 1 + min(l_depth, r_depth);
}
Leetecode 226
226. Invert Binary Tree
Invert a binary tree.
- 思路:
通过递归的方式,实现二叉树的镜像翻转。
void invertTreeCore(TreeNode* root) {
if (root->left)
invertTreeCore(root->left);
if (root->right)
invertTreeCore(root->right);
swap(root->left, root->right);
}
TreeNode* invertTree(TreeNode* root) {
if (!root)
return root;
invertTreeCore(root);
return root;
}
Leetecode 100
100. Same Tree
Given the roots of two binary trees p and q, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.
- 思路:
判断两棵树是否相同,使用递归方法,首先判断当前节点是否相同:
- 如果都为空,那么返回true;
- 如果都不空,那么判断值是否相等;
2.1 如果值相等那么递归判断左子树和右子树是否相同;
2.2 如果值不相等,那么返回false - 其他情况,说明一个为空,一个不空,那么返回false;
bool isSameTree(TreeNode* p, TreeNode* q) {
if (!p && !q)
return true;
else if (p && q)
if (p->val == q->val)
return (isSameTree(p->left, q->left) && isSameTree(p->right, q->right));
return false;
}
Leetecode 101
101. Symmetric Tree
Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center)…
- 思路:
使用递归方法,如果整棵树对称,那么根节点的左右两个子树应该形成对称,所以本质为判断两个树是否为对称。
这个问题需要注意的地方是递归的终止条件:
- 两个节点都为空,那么返回true且终止;
- 两个节点一个为空,一个不空那么返回false且终止;
- 两个节点都不为空,但是值不相等,那么返回false且终止。
- 两个节点都不空且值相等,那么继续递归左右子树。
bool isSubSymmetric(TreeNode* left_root, TreeNode* right_root) {
// both null
if (!left_root && !right_root)
return true;
// one null, one has
if (!left_root || !right_root)
return false;
// both have but not equal
if (left_root && right_root)
if (left_root->val != right_root->val)
return false;
return (isSubSymmetric(left_root->left, right_root->right) &&
isSubSymmetric(left_root->right, right_root->left));
}
bool isSymmetric(TreeNode* root) {
if (!root)
return true;
return isSubSymmetric(root->left, root->right);
}
Leetecode 222
222. Count Complete Tree Nodes
- 思路:
计算一颗完全二叉树的总节点数,思路类似与leetcode104,直接使用递归的方法。
int countNodes(TreeNode* root) {
if (!root)
return 0;
return 1 + countNodes(root->left) + countNodes(root->right);
}
Leetecode 110
110. Balanced Binary Tree
Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the left and right subtrees of every node differ in height by no more than 1.
- 思路:
使用递归求树的高度的思路,在求高度的同时,判断左右子树的高度差是否大于1,如果大于1那么设置返回值为false。
bool res = true;
int treeHeight(TreeNode* root) {
if (!root)
return 0;
int left_height = treeHeight(root->left);
int right_height = treeHeight(root->right);
if (abs(left_height - right_height) > 1)
res = false;
return 1 + max(left_height, right_height);
}
bool isBalanced(TreeNode* root) {
treeHeight(root);
return res;
Leetecode 112
112. Path Sum
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.
- 思路:
使用递归方法,转换为分别求root的左右子树问题,此时targetSum为减掉root->val后的值,当到叶子节点时,判断targetSum与该叶子节点之差是否为0。
注意:只有到达叶子节点时才开始判断,对于只有一边有子树的节点,对于没有子树的一边默认返回false即可。
// 写法1;
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root)
return false;
if (!root->left && !root->right) {
if (targetSum == root->val)
return true;
else
return false;
}
bool left = false; // 单边情况,没有子树的一边默认为false
bool right = false;
if (root->left)
left = hasPathSum(root->left, targetSum - root->val);
if (root->right)
right = hasPathSum(root->right, targetSum - root->val);
return left || right;
}
// 写法2:
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root) // 如果根为空或者只有单边的情况,返回false
return false;
if (!root->left && !root->right) { // 到达叶子节点
if (targetSum == root->val)
return true;
else
return false;
}
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
Leetecode 404
404. Sum of Left Leaves
Find the sum of all left leaves in a given binary tree…
- 思路:
求一个树的所有左叶子节点的和。该问题可以首DFS或BFS寻找所有的做叶子节点,然后求和。同时也
可以使用递归的方法解决。- 实现1
使用辅助函数,记录当前递归到的节点是否为左节点,再次基础上判断是否为叶子节点。
- 实现1
int sumOfLeftLeavesCore(TreeNode* root, bool is_left) {
if (!root)
return 0;
if (!root->left && !root->right) {
if (is_left)
return root->val;
else
return 0;
}
return sumOfLeftLeavesCore(root->left, true) + sumOfLeftLeavesCore(root->right, false);
}
int sumOfLeftLeaves(TreeNode* root) {
if (!root)
return 0;
return sumOfLeftLeavesCore(root->left, true) + sumOfLeftLeavesCore(root->right, false);
}
- 实现2
直接在递归中判断当前节点的左节点是否为叶子节点。
int sumOfLeftLeaves(TreeNode* root) {
if (!root)
return 0;
if (root->left && !root->left->left && !root->left->right)
return root->left->val + sumOfLeftLeaves(root->right);
return sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
Leetecode 257
257. Binary Tree Paths
Given the root of a binary tree, return all root-to-leaf paths in any order.
- 思路:
本质时二叉树的深度优先遍历。到达叶子节点时输出从根到叶子节点的路径。可以使用递归和迭代两种方法解决。
// 1. 递归方法
void binaryTreePathsCore(TreeNode* root, vector<int>& nums, vector<string>& res){
nums.push_back(root->val);
if (!root->left && !root->right) {
string str;
for (int i = 0; i < nums.size(); ++ i) {
str += to_string(nums[i]);
if (i < (nums.size() - 1))
str += "->";
}
res.push_back(str);
nums.pop_back();
return;
}
if (root->left)
binaryTreePathsCore(root->left, nums, res);
if (root->right)
binaryTreePathsCore(root->right, nums, res);
nums.pop_back();
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if (!root)
return res;
vector<int> nums;
binaryTreePathsCore(root, nums, res);
return res;
}
// 2. 迭代方法(基于后序遍历的DFS):
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if (!root)
return res;
stack<TreeNode*> stk;
TreeNode* node = root;
TreeNode* last;
vector<int> nums;
while (node || !stk.empty()) {
if(node) {
stk.push(node);
nums.push_back(node->val);
node = node->left;
} else {
node = stk.top();
if (node->right && last != node->right) {
node = node->right;
} else {
if (!node->left && !node->right) {
string str;
for (int i = 0; i < nums.size(); ++ i) {
str += to_string(nums[i]);
if (i < (nums.size() - 1))
str += "->";
}
res.push_back(str);
}
stk.pop();
nums.pop_back();
last = node;
node = nullptr;
}
}
}
return res;
}
Leetecode 113
113. Path Sum II
Given the root of a binary tree and an integer targetSum, return all root-to-leaf paths where each path’s sum equals targetSum.
A leaf is a node with no children.
- 思路:
本质是二叉树的深度优先遍历,返回所有和为targetSum的节点路径。可以通过递归和迭代两种方法,其中迭代方法是由后续遍历即可。
- 递归方法
每次递归需要将targetSum减去当前节点的val。
// all root must NOT be nullptr;
void pathSumCore(TreeNode* root, int targetSum,
vector<int>& ints, vector<vector<int> >& res) {
ints.push_back(root->val);
if (!root->left && !root->right) { // 到达叶子节点
if (targetSum == root->val) { // 和满足要求
res.push_back(ints);
}
ints.pop_back();
return;
}
if (root->left)
pathSumCore(root->left, targetSum - root->val, ints, res); // 注意targetSum的改变
if (root->right)
pathSumCore(root->right, targetSum - root->val, ints, res);
ints.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int> > res;
if (!root)
return res;
vector<int> ints;
pathSumCore(root, targetSum, ints, res);
return res;
}
- 迭代方法
基于后续遍历的DFS,要注意在迭代过程中targetSum要减去当前节点val,同时在stack中有pop的时候要将targetSum的值恢复。
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int> > res;
if (!root)
return res;
TreeNode* node = root;
TreeNode* last = nullptr;
stack<TreeNode*> stk;
vector<int> nums;
while (node || !stk.empty()) {
if (node) {
stk.push(node);
nums.push_back(node->val);
targetSum -= node->val; // 注意targetSum的变化
node = node->left;
} else {
node = stk.top();
if (node->right && last != node->right) {
node = node->right;
} else {
if (!node->left && !node->right && targetSum == 0) { // 到达叶子节点且targetSum为0
res.push_back(nums); // 记录
}
stk.pop();
nums.pop_back();
targetSum += node->val; // 注意targetSum的变化(恢复)
last = node;
node = nullptr;
}
}
}
return res;
}
Leetecode 129
129. Sum Root to Leaf Numbers
You are given the root of a binary tree containing digits from 0 to 9 only.
Each root-to-leaf path in the tree represents a number.
For example, the root-to-leaf path 1 -> 2 -> 3 represents the number 123.
Return the total sum of all root-to-leaf numbers.
A leaf node is a node with no children.
- 思路:
二叉树中假设从root到leaf的节点组成一个整数,然后求所有这些整数的和。
解题思路是递归的思路,整数的构造方法为root到父节点所代表的整数* 10 + 当前节点
,从而形成递归,属于二叉树的DFS,实现方式有两种,分别是递归和迭代。
需要注意的是变量的还原。
- 递归方法:
// recurrent
void sumNumbersCore(TreeNode* root, int& sub_sum, int& sum) {
sub_sum = 10 * sub_sum + root->val; // root到父节点所代表的整数* 10 + 当前节点
if (!root->left && !root->right) { // leaf node
sum += sub_sum;
}
if (root->left)
sumNumbersCore(root->left, sub_sum, sum);
if (root->right)
sumNumbersCore(root->right, sub_sum, sum);
sub_sum = (sub_sum - root->val) / 10; // 变量还原
}
int sumNumbers(TreeNode* root) {
int sum = 0;
if (!root)
return sum;
int sub_sum = 0;
sumNumbersCore(root, sub_sum, sum);
return sum;
}
- 迭代方法:
int sumNumbers(TreeNode* root) {
int sum = 0;
if (!root)
return sum;
stack<TreeNode*> stk;
TreeNode* last = nullptr;
TreeNode* node = root;
int sub_sum = 0;
while (node || !stk.empty()) {
if (node) {
stk.push(node);
sub_sum = 10 * sub_sum + node->val; // root到父节点所代表的整数* 10 + 当前节点
node = node->left;
} else {
node = stk.top();
if (node->right && last != node->right) {
node = node->right;
} else {
if (!node->left && !node->right) {
sum += sub_sum;
}
sub_sum = (sub_sum - node->val) / 10; // 变量还原
stk.pop();
last = node;
node = nullptr;
}
}
}
return sum;
}
Leetecode 437
437. Path Sum III
You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
- 思路:
该问题要求找出二叉树中所有和满足targetSum的路径的数量,该路径的起点和终点都没有要求,因此接替思路为遍历二叉树所有节点,将每个节点都作为起点(终点没有要求)寻找其满足条件的路径数量,然后将路径数量求和。也就是说,
总路径数量 = 当前节点为起点的路径数量+当前节点的左孩子为起点的路径数量+当前节点的右孩子为起点的路径数量
。
从而形成递归。而求解当前节点为起点的路径数量的方法也是通过递归完成的。
void pathSumCore(TreeNode* node, int& count, int targetSum) {
if (targetSum == node->val)
count++;
if (node->left)
pathSumCore(node->left, count, targetSum - node->val);
if (node->right)
pathSumCore(node->right, count, targetSum - node->val);
}
int pathSum(TreeNode* root, int sum) {
if (!root)
return 0;
int count = 0;
pathSumCore(root, count, sum);
int left = pathSum(root->left, sum);
int right = pathSum(root->right, sum);
return count + left + right;
}
Leetecode 235
235. Lowest Common Ancestor of a Binary Search Tree
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
- 思路:
在一个二叉搜索树中寻找两个节点的最低公共祖先。可通过递归实现,根据题目说明,可以得知当某节点值位于两个指定节点值之间时,那么该接待你即为公共祖先。所以只需要从root节点寻找,当root值大于两个指定节点值的最大值时,再从root->left进行寻找;反之从root->right进行寻找。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root)
return nullptr;
if (root->val > max(p->val, q->val))
return lowestCommonAncestor(root->left, p, q);
if (root->val < min(p->val, q->val))
return lowestCommonAncestor(root->right, p, q);
return root;
}