当前位置: 首页剑指offer刷题第六期问题详情 【回溯专题】剑指 Offer 34. 二叉树中和为某一值的路径 本问题对应课程链接:剑指offer刷题第六期 要求: 1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。 2、给出你代码所用的时间复杂度和空间复杂度
共以下 10 个回答
时间复杂度:O(n)
空间复杂度:O(n)
打卡
时间复杂度:O(n)
空间复杂度:O(n)
思路:二叉树dfs
“`c++> &ans, vector current, TreeNode* cur, int sum, int target) {
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void dfs(vector
if (cur == nullptr) return;
};
“`
时间复杂度O(N),空间复杂度O(N)
“`C++> pathTarget(TreeNode* root, int target) {> res; tmp;
class Solution {
public:
vector
vector
vector
};
“`
回溯算法,注意这个算法是在二叉树一般递归算法的基础上,将存储路径的List变成了可复用的回溯栈,空间复杂度降低为$O(m)$(m为树的最大深度),空间复杂度$O(n)$
/**> pathTarget(TreeNode root, int target) { > path(TreeNode node,int target){ > path = new ArrayList<>(); p = new ArrayList<>(); > lpath = path(node.left ,target – node.val); > rpath = path(node.right ,target – node.val);
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List
return path(root,target);
}
private List<List
List<List
if(node null )
return path;
if(target – node.val 0 && node.left null && node.right null){
List
p.addFirst(node.val);
path.add(p);
return path;
}
List<List
if(lpath!=null){
for(int i = 0; i < lpath.size(); i++){
lpath.get(i).addFirst(node.val);
path.addFirst(lpath.get(i));
}
}
List<List
if(rpath!=null){
for(int i = 0; i < rpath.size(); i++){
rpath.get(i).addFirst(node.val);
path.addFirst(rpath.get(i));
}
}
return path;
}
}
//空间复杂度O(n)
//时间复杂度O(n)
/**> pathTarget(TreeNode root, int target) { path; > res;
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector
dfs(root, target);
return res;
}
private:
vector
vector<vector
void dfs(TreeNode* root, int target) {
if(root nullptr) return;
path.push_back(root->val);
target -= root->val;
if(root->left nullptr && root->right nullptr && target 0) {//叶子节点
res.push_back(path);
}
dfs(root->left, target);
dfs(root->right, target);
path.pop_back();
}
};
使用深度优先搜索,下面代码的第7行是回溯目标值,没有这一行也可以得到正确答案,这是为什么?
这是因为在这段代码中,目标值 target 是通过函数参数传递给递归调用的 dfs 函数的。每次递归调用时,都会创建一个新的函数调用栈帧,其中包含了当前的 target 值。而在回溯的过程中,每次递归调用返回时,函数调用栈帧也会被弹出,从而恢复到上一层节点的状态,包括了目标值 target。因此,即使在回溯的过程中没有手动恢复目标值 target,它也会在函数调用栈的机制下自动地恢复到正确的状态。
尽管在这个特定的情况下不添加 target += root->val 这一行代码也能得到正确的答案,但在一般情况下,为了代码的健壮性和可读性,最好在回溯的过程中手动恢复相关的状态。这可以确保代码的正确性,并且使得代码更容易理解和维护。