文章内容是自己刷leetcode题目的一些总结。
文章内容参考公众号: 代码随想录。
喜欢的话,希望大家可以点点赞 ^ - ^
一.题目描述
二.题目分析
我们需要找到所有路径,要用到递归+回溯。
使用path保存每条路径,遇到叶子节点就把path加入到答案ans中去。
使用前序遍历,每次先将节点加入到path,终止条件为遇到叶子节点,也就是该节点的左右孩子都为空的节点,注意,要先将节点加入path,再进行终止条件的判断,否则叶子节点会加不进去。单次递归逻辑为:递归左右子树,递归完成后记得回溯。
三.递归代码
class Solution {
public:
void getPath(TreeNode* node, vector<int>& path, vector<string>& ans) {
path.push_back(node->val); //中
//终止条件:遇到叶子节点
if(node->left == nullptr && node->right == nullptr) {
string sPath;
for(int i = 0; i < path.size() - 1; i ++) {
sPath += to_string(path[i]);
sPath += "->";
}
sPath += to_string(path[path.size() - 1]);
ans.push_back(sPath);
}
//单次逻辑:递归+回溯
if(node->left) { //左
getPath(node->left, path, ans);
path.pop_back();
}
if(node->right) { //右
getPath(node->right, path, ans);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
//使用递归+回溯
//因为要记录路径,所以采用前序遍历
vector<int> path;
vector<string> ans;
if(root == nullptr) return ans;
getPath(root, path, ans);
return ans;
}
};
四.拓展:路径总和
1.题目描述
2.题目分析
这道题目其实与我们刚刚讲的二叉树的所有路径很相似。我们可以在找到一条路径path后将该路径的节点的值求和来判断是不是我们需要的那条路径。找到后做一个标记返回。
改进:其实我们不用统计每条路径之后再按照路径求和,我们可以在和的基础上进行减法,当遇到叶子节点时,减到了0说明找到路径,否则就是没找到。
因为我们的目标是找到一条路径即可,所以不用遍历整个树,返回值采用bool。
3.递归代码
原始:
class Solution {
public:
int flag = 0;
bool hasSum(TreeNode* node, int n, vector<int>& path) {
// if(node == nullptr) return false;
path.push_back(node->val);
if(node->left == nullptr && node->right == nullptr) {
int sum = 0;
for(int i = 0; i < path.size() - 1; i ++) {
sum += path[i];
}
sum += path[path.size() - 1];
if(sum == n) {
flag = 1;
return true;
}
else return false;
}
if(node->left) {
hasSum(node->left, n, path);
path.pop_back();
}
if(node->right) {
hasSum(node->right, n, path);
path.pop_back();
}
if(flag == 1) {
return true;
} else {
return false;
}
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
vector<int> path;
return hasSum(root, targetSum, path);
}
};
改进:
class Solution {
public:
bool hasSum(TreeNode* node, int cnt) {
//因为我们不用遍历整棵树,找到一条合适的边就可以返回,所以用bool
//终止条件
if(!node->left && !node->right && cnt == 0) return true; //找到了
if(!node->left && !node->right) return false; //没找到
//递归逻辑
if(node->left) {
cnt -= node->left->val;
if(hasSum(node->left, cnt)) return true;
cnt += node->left->val; //回溯
}
if(node->right) {
cnt -= node->right->val;
if(hasSum(node->right, cnt)) return true;
cnt += node->right->val; //回溯
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
return hasSum(root, targetSum - root->val);
}
};
五.总结
在这次题解中,我们用到了回溯,其实递归与回溯是相伴相生的,我会在二叉树的章节更新完成后,开始给大家讲解回溯的相关题目。