题型1:easy
深度优先搜索
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum)
{
if (root == NULL)
return false;
if (targetSum == root->val && root->left == NULL && root->right == NULL) return true;
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
};
广度优先搜索
- 记录根节点到每个节点的路径总和,防止重复计算
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum)
{
if (root == NULL)
return false;
queue<pair<TreeNode*, int>> q;
q.push({ root,root->val });
while (!q.empty())
{
int sum = q.front().second;
TreeNode* temp = q.front().first;
q.pop();
if (!temp->left && !temp->right)
{
if(sum==targetSum)
return true;
continue;
}
//同时朝着当前根节点的左右子树探索
//探索的同时记录根节点到每个节点的路径和
if (temp->left)
q.push({ temp->left,temp->left->val + sum });
if (temp->right)
q.push({ temp->right,temp->right->val+sum });
}
return false;
}
};
类回溯法
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum)
{
if (root == NULL)
return false;
return backTravel(root,targetSum,root->val);
}
bool backTravel(TreeNode* root,int targetSum,int sum)
{
bool Lfind=false, Lright=false;
if (!root) return false;
if (!root->left && !root->right &&sum == targetSum)
return true;
if (root->left)
Lfind=backTravel(root->left, targetSum, sum+root->left->val);
if (root->right)
Lright = backTravel(root->right, targetSum, sum+root->right->val);
return Lfind || Lright;
}
};
题型2:medium
回溯模板解题
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum)
{
vector<vector<int>> ret;
if (root == NULL)
return ret;
vector<int> cur;
backTrave(ret,cur,root, targetSum);
return ret;
}
void backTrave(vector<vector<int>>& ret, vector<int>& cur, TreeNode* root, int targetSum)
{
if (root == NULL) return;
if (root->left == NULL && root->right == NULL)
{
cur.push_back(root->val);
if (accumulate(cur.begin(), cur.end(), 0) == targetSum)
ret.push_back(cur);
//如果当前是找到了一个解,那么回溯,寻找其他可能解
//如果当前节点是叶子节点,那么再往下找,也不会得到正确解,也需要回溯
cur.pop_back();
return;
}
else
{
cur.push_back(root->val);
//先从左子树开始找,如果无法找到合适解,去右子树里面找
//如果左子树里面找到了合适解,要去右子树里面找还有无其他合适解
backTrave(ret, cur, root->left, targetSum);
backTrave(ret, cur, root->right, targetSum);
//如果当前左右子树都无法找到合适解,说明当前根的两个分支走不通,需要返回上一层,寻找别的路径走
//那么进行回溯,来到上一层,走另一个分支,即如果当前根是上一层的左子树,那么回到上一层后需要到右子树里面寻找可能解
cur.pop_back();
}
}
};
回溯模板第二种简化写法
class Solution {
public:
vector<vector<int>> ret;
vector<int> path;
void dfs(TreeNode* root, int sum) {
if (root == nullptr) {
return;
}
path.emplace_back(root->val);
sum -= root->val;
if (root->left == nullptr && root->right == nullptr && sum == 0) {
ret.emplace_back(path);
}
dfs(root->left, sum);
dfs(root->right, sum);
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int sum) {
dfs(root, sum);
return ret;
}
};
广度优先遍历—BFS
- 先来看看BFS的两个模板
- 模板一:如果不需要确定当前遍历到了哪一层,BFS模板如下
while queue 不空:
cur = queue.pop()
if cur 有效且未被访问过:
进行处理
for 节点 in cur 的所有相邻节点:
if 该节点有效:
queue.push(该节点)
- 模板二:如果要确定当前遍历到了哪一层,BFS模板如下。
这里增加了level表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size表示在当前遍历层有多少个元素,也就是队列中的元素数,我们把这些元素一次性遍历完,即把当前层的所有元素都向外走了一步。
level = 0
while queue 不空:
size = queue.size()
while (size --) {
cur = queue.pop()
if cur 有效且未被访问过:
进行处理
for 节点 in cur的所有相邻节点:
if 该节点有效:
queue.push(该节点)
}
level ++;
上面两个是通用模板,在任何题目中都可以用,是要记住的!
- 本题的解法:本题要求所有的路径,不需要按层遍历,因此使用模板一。
- 我们也可以采用广度优先搜索的方式,遍历这棵树。当我们遍历到叶子节点,且此时路径和恰为目标和时,我们就找到了一条满足条件的路径。
- 为了节省空间,我们使用哈希表记录树中的每一个节点的父节点。每次找到一个满足条件的节点,我们就从该节点出发不断向父节点迭代,即可还原出从根节点到当前节点的路径。
class Solution {
public:
vector<vector<int>> ret;
unordered_map<TreeNode*, TreeNode*> parent;
void getPath(TreeNode* node) {
vector<int> tmp;
while (node != nullptr) {
tmp.emplace_back(node->val);
node = parent[node];
}
reverse(tmp.begin(), tmp.end());
ret.emplace_back(tmp);
}
vector<vector<int>> pathSum(TreeNode* root, int sum) {
if (root == nullptr) {
return ret;
}
queue<TreeNode*> que_node;
queue<int> que_sum;
que_node.emplace(root);
que_sum.emplace(0);
while (!que_node.empty()) {
TreeNode* node = que_node.front();
que_node.pop();
int rec = que_sum.front() + node->val;
que_sum.pop();
if (node->left == nullptr && node->right == nullptr) {
if (rec == sum) {
getPath(node);
}
} else {
if (node->left != nullptr) {
parent[node->left] = node;
que_node.emplace(node->left);
que_sum.emplace(rec);
}
if (node->right != nullptr) {
parent[node->right] = node;
que_node.emplace(node->right);
que_sum.emplace(rec);
}
}
}
return ret;
}
};