题目意思
这个题目的意思和JZ24的题目几乎一模一样,就是对于从根节点到叶子节点的所组成的路径中。选择路径中的所有的权值之和等于给定的某一个数的路径。并且将他们返回。
前置知识。这个题目我用的分别是DFS和BFS进行处理的。其中DFS用了一个回溯的方法进行处理。
回溯法是一个DFS的技巧,就是当我们DFS遍历某一个子节点的时候,我们还需要回来遍历另一个子节点,为了消除之前遍历的时候的影响,我们需要将状态进行复原。结合下面的图理解回溯。
思路分析
- 好了我们知道了回溯和搜索的思想之后,这个题目就可以开始写了。
解法一 DFS
- 我们从根节点向下进行搜索。同时我们开一个二维的动态数组记录我们最后的答案。然后我们开一个一维的vector作为中间变量存储中间路径。
- 递归的边界: 当我们遍历到某一个节点没有左右子节点的时候。我们对当前存储的路径进行求和,判断是否满足题目给定的数字。
- 递归的前进段,我们判断是否可以向左或者向右进行递归。然后先将结点的值存入路径进行向下递归,然后回溯。
- 代码如下
- 进行DFS的时候需要遍历每一个点,时间复杂度为O(n)
- 需要存储所有的结点的信息,空间复杂度为O(n)
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @param sum int整型
* @return int整型vector<vector<>>
*/
vector<vector<int>> ans; // 将这个变量设为全局变量,减少参数的传递
void DFS(TreeNode* now,vector<int> path,int sum){
// 如果这个节点没有了左右子节点,就说明这个节点是叶子节点
if(now->left==NULL&&now->right==NULL){
int s=0;
// 计算所有的路径的和
for(auto x:path){
s+=x;
}
// 如果路径的和满足题目给定的数字
if(s==sum){
ans.push_back(path);
}
return;
}
// 单独遍历左边的子节点
if(now->left){
path.push_back(now->left->val);
DFS(now->left,path,sum);
// 回溯
path.pop_back();
}
// 单独遍历右边的子节点
if(now->right){
path.push_back(now->right->val);
DFS(now->right,path,sum);
// 回溯
path.pop_back();
}
}
vector<vector<int> > pathSum(TreeNode* root, int sum) {
// write code here
// 判断根节点为空的情况
if(!root){
return ans;
}
vector<int> path;
path.push_back(root->val);
DFS(root,path,sum);
return ans;
}
};解法二 BFS
- 对于DFS,如果树过深的话可能会存在爆栈的风险,所以我们一般也要掌握BFS的写法,其实思想还是搜索和回溯的思想。只是写法的不一样。
- 代码如下
- 进行BFS的时候需要遍历所有的结点,并且每个结点只会被遍历一遍,时间复杂度为O(n)
- 我们需要存储所有的结点的信息,空间复杂度为O(n)
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类
* @param sum int整型
* @return int整型vector<vector<>>
*/
vector<vector<int> > ans;
vector<vector<int> > pathSum(TreeNode* root, int sum) {
// write code here
if(!root){
return ans;
}
// 用来存储遍历过的结点
vector<TreeNode*> node;
// 用来存储中间路径
vector<int> s;
int SUM=0;
TreeNode* now=root;
TreeNode* pre;
while(now||!node.empty()){
// 一直往左边进行遍历,知道到达最左端
while(now){
SUM+=now->val;
node.push_back(now);
s.push_back(now->val);
now=now->left;
}
// 这步是回到上一个节点
now=node.back();
// 往右边走
if(now->right&&now->right!=pre){
now=now->right;
}else{
pre=now;
// 这个是一个叶子节点
if(!now->right&&!now->left){
if(SUM==sum){
ans.push_back(s);
}
}
// 回溯
SUM=SUM-now->val;
node.pop_back();
s.pop_back();
now=NULL;
}
}
return ans;
}
};
京公网安备 11010502036488号