题目描述
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径
思路还是比较好想的,用个递归来实现,先序遍历,
#include <iostream>
#include <vector>
using namespace std;
// 调试开关
#define __tmain main
#ifdef __tmain
#define debug cout
#else
#define debug 0 && cout
#endif // __tmain
#ifdef __tmain
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x)
:val(x), left(NULL), right(NULL)
{
}
};
#endif // __tmain
class Solution
{
public:
vector< vector<int> > m_res;
vector< vector<int> > FindPath(TreeNode* root, int expectNumber)
{
if(root == NULL)
{
return m_res;
}
vector<int> path;
FindPath(root, expectNumber, path, 0);
return m_res;
}
void FindPath(TreeNode* root, int expectNumber, vector<int> path, int currentSum)
{
currentSum += root->val;
path.push_back(root->val);
///
if(currentSum == expectNumber
&& ((root->left == NULL && root->right == NULL)))
{
debug <<"find a path" <<endl;
for(int i = 0; i < path.size( ); i++)
{
debug <<path[i] <<" ";
}
debug <<endl;
m_res.push_back(path);
}
if(root->left != NULL)
{
FindPath(root->left, expectNumber, path, currentSum);
}
if(root->right != NULL)
{
FindPath(root->right, expectNumber, path, currentSum);
}
// 此处不需要恢复currentSum和path的值:
// 因为currentSum作为参数在函数递归调用返回时会自动恢复
// 而如果作为静态局部变量存储则需要进行恢复
//currentSum -= root->val;
//path.pop_back( );
}
};
或者
class Solution
{
public:
vector< vector<int> > m_res;
vector< vector<int> > FindPath(TreeNode* root, int expectNumber)
{
if(root == NULL)
{
return m_res;
}
vector<int> path;
FindPathRecursion(root, expectNumber);
return m_res;
}
void FindPathRecursion(TreeNode* root, int expectNumber)
{
static int currentSum = 0;
static vector<int> path;
currentSum += root->val;
path.push_back(root->val);
debug <<"currentSum = " <<currentSum - root->val <<", now get " <<root->val <<", currentSum = "<<currentSum <<endl;
///
if(currentSum == expectNumber
&& ((root->left == NULL && root->right == NULL)))
{
debug <<"find a path" <<endl;
for(int i = 0; i < path.size( ); i++)
{
debug <<path[i] <<" ";
}
debug <<endl;
m_res.push_back(path);
}
if(root->left != NULL)
{
FindPathRecursion(root->left, expectNumber);
}
if(root->right != NULL)
{
FindPathRecursion(root->right, expectNumber);
}
debug <<"currentSum = " <<currentSum <<", now pop " <<*(path.end( ) - 1) <<", currentSum = "<<currentSum - root->val<<endl;
// 作为静态变量存储需要恢复现场
currentSum -= root->val;
path.pop_back( );
}
};
在递归的过程中,用static的变量保存path参数的信息,用于这个变量在函数的静态生存周期内部,因此这种方法有个致命的缺点
所有的对象共享这个函数,当多个对象同时操作的时候,path变量只有一个副本,因此线程不安全。
如果在函数结束的时候,path变量没有被清空,那么即使不是多线程共享访问,两个对象顺序的访问这个对象,依然会造成根共享访问同样的问题
我们会在解决第27题的过程中,就会体会到这个问题
#include <iostream>
#include <vector>
using namespace std;
// 调试开关
#define __tmain main
#ifdef __tmain
#define debug cout
#else
#define debug 0 && cout
#endif // __tmain
#ifdef __tmain
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
// TreeNode(int x)
// :val(x), left(NULL), right(NULL)
// {
// }
};
#endif // __tmain
class Solution
{
public:
vector< vector<int> > FindPath(TreeNode* root, int expectNumber)
{
vector< vector<int> > res;
if(root == NULL)
{
return res;
}
FindPath(root, expectNumber, res);
return res;
}
protected :
void FindPath(TreeNode* root, int leftSum, vector< vector<int> > &res)
{
if(root == NULL)
{
return;
}
/// 用一个静态的变量来存储路径
static vector<int> path;
leftSum -= root->val;
path.push_back(root->val);
///
if(leftSum == 0
&& ((root->left == NULL && root->right == NULL)))
{
debug <<"find a path" <<endl;
for(int i = 0; i < path.size( ); i++)
{
debug <<path[i] <<" ";
}
debug <<endl;
res.push_back(path);
cout <<"size = " <<res.size( ) <<endl;
}
else
{
if(root->left != NULL)
{
FindPath(root->left, leftSum, res);
}
if(root->right != NULL)
{
FindPath(root->right, leftSum, res);
}
}
leftSum += root->val;
path.pop_back( );
}
};
int __tmain( )
{
// 0 1 2 3 4
// {10,5,12,4,7},22
TreeNode tree[5];
tree[0].val = 10;
tree[0].left = &tree[1];
tree[0].right = &tree[2];
tree[1].val = 5;
tree[1].left = &tree[3];
tree[1].right = &tree[4];
tree[2].val = 12;
tree[2].left = NULL;
tree[2].right = NULL;
tree[3].val = 4;
tree[3].left = NULL;
tree[3].right = NULL;
tree[4].val = 7;
tree[4].left = NULL;
tree[4].right = NULL;
Solution solu;
vector< vector<int> > res = solu.FindPath(&tree[0], 15);
cout <<"size = " <<res.size( ) <<endl;
for(int i = 0; i < res.size( ); i++)
{
for(int j = 0; j < res[i].size( ); j++)
{
cout <<res[i][j] <<" ";
}
cout <<endl;
}
return 0;
}