首先要说明二叉树的问题就是用递归来做,基本没有其他方法,因为这数据结构基本只能用递归遍历,不要把事情想复杂了。

#112 Path Sum

原题链接:https://leetcode.com/problems/path-sum/

判断从树的根节点到叶子节点的路径中,是否有一条所有节点上的值之和和特定的数字,即sum

从根节点到叶子节点,线路的起点的是固定的,只需要不断递归下去,判断在叶子节点处是否满足根节点加到该节点的值之和为sum

这个限制条件把这个问题简化了很多很多。

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if (!root) return false;
if (root->val == sum && root->left == NULL && root->right == NULL) return true;
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
}
};

#113 Path Sum II

与前题要做的事情一致,只是现在要求输出路径。如果路径有多条,要求输出多条路径。

要输出路径,在递归的过程中肯定是要有一个传址的变量vector<int>将路径记录下来。有多条路径,需要把多条路径vector<vector<int> >记录下来。

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int> > paths;
vector<int> path;
pathSumHelper(root, sum, path, paths);
return paths;
}
private:
void pathSumHelper(TreeNode* root, int sum, vector<int>& path, vector<vector<int>>& paths) {
if (root == NULL) return;
path.push_back(root->val);
if (root->val == sum && root->left == NULL && root->right == NULL) {
paths.push_back(path);
}
pathSumHelper(root->left, sum - root->val, path, paths);
pathSumHelper(root->right, sum - root->val, path, paths);
path.pop_back();
}
};

这里有一点搞不懂,为什么最后要进行path.pop_back(),如果我把代码写成这样子:

    void pathSumHelper(TreeNode* root, int sum, vector<int>& path, vector<vector<int>>& paths) {
if (root == NULL) return;
path.push_back(root->val);
if (root->left == NULL && root->right == NULL) {
if (root->val == sum) {
paths.push_back(path);
}
path.pop_back();
}
pathSumHelper(root->left, sum - root->val, path, paths);
pathSumHelper(root->right, sum - root->val, path, paths);
}

然后,发现如果这么写我是错的。对于下面的这一棵二叉树,得到的结果是[[5,4,11,2],[5,4,11,8,4,5]],正确结果是[[5,4,11,2],[5,8,4,5]]。第二条路径中多了4, 11,问题出在只是把根节点去除掉,没有去除中间节点,使得中间节点及其子孙节点中的中间节点出现在了经过其兄弟节点的路径。

如,左侧的4节点会留在右子树的路径中是因为,调用根节点的pathSumHelper时,会调用两次pathSumHelper(root->left/* node 4 */, sum - root->val, path, paths);pathSumHelper(root->right/* node 8 */, sum - root->val, path, paths);,在第一次调用完成之后,path变量中的4节点未被删除,所以存留在了路径[5,4,11,8,4,5]中(就是第一个4)。

#437 Path Sum III

继续,判断是否存在路径上的值之和为特定的数字sum。变化在于起点不固定、终点也不固定,值存在负数(其实无所谓,因为前面的代码没有判断数值超过sum就不再递归)。最后的输出是路径的条数。

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if (!root) return 0;
return sumUp(root, 0, sum) + pathSum(root->right, sum) + pathSum(root->left, sum);
} private:
int sumUp(TreeNode* root, int pre, int sum) {
if (!root) return 0;
int current = pre + root->val;
return (current == sum) + sumUp(root->right, current, sum) + sumUp(root->left, current, sum); // 如果当前节点能够满足条件,有一条路径了,但是还是要继续搜索左右子树,因为值不全为非负,这里返回的路径都具有同一个根节点。
}
};

这里有两个递归函数,函数pathSumreturn sumUp(root, 0, sum) + pathSum(root->right, sum) + pathSum(root->left, sum);是以该节点root为起点的路径条数、以root->right为起点或者以其子孙节点为起点的路径条数、以root->left为起点或者以其子孙节点为起点的路径条数。

[LeetCode] #112 #113 #437 Path Sum Series的更多相关文章

  1. LeetCode 112. 路径总和(Path Sum) 10

    112. 路径总和 112. Path Sum 题目描述 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和. 说明: 叶子节点是指没有子节点的节 ...

  2. LeetCode(113) Path Sum II

    题目 Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given ...

  3. leetcode 112. Path Sum 、 113. Path Sum II 、437. Path Sum III

    112. Path Sum 自己的一个错误写法: class Solution { public: bool hasPathSum(TreeNode* root, int sum) { if(root ...

  4. 47. leetcode 437. Path Sum III

    437. Path Sum III You are given a binary tree in which each node contains an integer value. Find the ...

  5. 【leetcode】437. Path Sum III

    problem 437. Path Sum III 参考 1. Leetcode_437. Path Sum III; 完

  6. 437. Path Sum III

    原题: 437. Path Sum III 解题: 思路1就是:以根节点开始遍历找到适合路径,以根节点的左孩子节点开始遍历,然后以根节点的右孩子节点开始遍历,不断循环,也就是以每个节点为起始遍历点 代 ...

  7. Leetcode 931. Minimum falling path sum 最小下降路径和(动态规划)

    Leetcode 931. Minimum falling path sum 最小下降路径和(动态规划) 题目描述 已知一个正方形二维数组A,我们想找到一条最小下降路径的和 所谓下降路径是指,从一行到 ...

  8. [LeetCode] 437. Path Sum III 路径和 III

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

  9. [LeetCode] 437. Path Sum III_ Easy tag: DFS

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

随机推荐

  1. Task的运行原理和工作窃取

    在net4.0以前,当调用ThreadPool.QueueUserWorkItem方法往线程池中插入作业时,会把作业内容(其实就是一个委托)放到线程池中的一个全局队列中,然后线程池中的线程按照先进先出 ...

  2. 浅析Web数据存储-Cookie、UserData、SessionStorage、WebSqlDatabase

    Cookie 它是标准的客户端浏览器状态保存方式,可能在浏览器诞生不久就有Cookie了,为什么需要Cookie 这个东东?由于HTTP协议没有状态,所以需要一个标志/存储来记录客户浏览器当前的状态, ...

  3. ASP.NET Core 2 学习笔记

    之前的ASP.NET网站,只要把*.html.*.css.*.jpg.*.png.*.js等静态文件放在项目根目录,默认都可以直接被浏览:但ASP.NET Core 小改了浏览静态文件的方式,默认根目 ...

  4. Theme Section HDU - 4763(些许暴力)

    题意: 求出最长公共前后缀 不能重叠  而且 这个前后缀 在串的中间也要出现一次 解析: 再明确一次next数组的意思:完全匹配的最长前后缀长度 求一遍next 然后暴力枚举就好了 #include ...

  5. c++11 右尖括号>改进

    c++11 右尖括号>改进 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> # ...

  6. 前端学习 -- Xhtml语法规范

    Xhtml语法规范 HTML中不区分大小写,但是尽量使用小写: HTML的注释不能嵌套: 标签必须结构完整{要么成对出现,要么自结束标签,虽然浏览器会帮我们修正一些不符合规范的内容} 标签可以嵌套但是 ...

  7. 解题:POI 2011 Strongbox

    首先洛谷的题面十分的劝退(至少对我这个菜鸡来说是这样),我来解释一下(原来的英文题面): 有一个有若干个密码(每个密码都可以开箱子)的密码箱,密码是在$0$到$n-1$的数中的,且所有的密码都满足一个 ...

  8. 解题:POI 2007 Driving Exam

    题面 有点意思的题 从一个位置$i$出发可以到达每一个位置即是从$1,n$出发可以到达$i$.然后有了一个做法:把图上下反转后建反图,这样就可以求从一个点$i$到达左右两侧的花费$dp[i][0/1] ...

  9. js replace如何实现replaceAll

    js下string对象的replace方法的定义如下: stringObject.replace(regexp/substr,replacement) 其中: 参数             |     ...

  10. [转载]hzwer的bzoj题单

    counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ120 ...