今天回顾了一下二叉树给定sum的问题,逻辑还是有问题,本以为对的,写了如下的代码
bool hasPathSum(TreeNode *root, int sum) {
if(root==NULL && sum==0) return true;
TreeNode* p=root;
stack<TreeNode* > S;
int path=0;
while(!S.empty()||p!=NULL)
{
while(p!=NULL)
{
S.push(p);
path+=p->val;
p=p->left;
}
if(path==sum) return true;
p=S.top();
S.pop();
if(p->left!=NULL)
path-=p->left->val;
p=p->right;
}
return false;
}
但是发现其实,path记录的时候有问题,尤其是右子树回退的时候是回退两次,所以这个就挂了一开始分析,发现这里面三个数据结构要跟踪,p, Stack内容,path值,所以还是没弄清楚,除了bug
确实while结束之后,就是访问叶子结点的位置,而且左子树回退的时候,就是path-=p->left->val,如果left有的话,没有就不减。
但是我用数据跑了下,右边的都detect不到,分析见下图
也就是说,从右子树4回退,指针回一次回退两次到1,因为之前的2在走2->4的时候,已经从stack pop出来了,所以回到1的时候,只减了2,没减4,就在这时我突然想到可以直接再- p->left->right->val啊,之前怎么没想到,就这么在写博客的时候想到了解决方案,但是不确定是否完全正确。感觉要么从左子树回退,看是否空来- 要么右子树回退,就是回退两次,然后path- = 两次
但是从leetcode反馈来看,似乎还有问题。
分析出来,似乎还有从右子树的右子树回退两次的情况,因此还是会挂,所以这条路不确定是否可以走通
于是乎回顾了当年4月份的帖子,写的基于先序递归算法的pathsum代码,然后记录所有路径也是,但是记录路径可能用vector来模拟栈比较好,可以直接push_back,stack没有迭代器,没法copy到一个vector,除非一个一个pop出来,放在queue里,但是还要push回去,很麻烦,所以vector了。另外vector还可以模拟类似队列的结构,例如编程之美层序遍历打印层结束的代码;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
bool HasPathSum=false;
vector<vector<int> >allpathvec;
vector<int> pathvec;
void PreOrder(TreeNode* root, int sum, int &path)
{
if(root!=NULL)
{
//cout<<root->val;
path+=root->val;
pathvec.push_back(root->val);
if(root->left==NULL && root->right==NULL && path==sum)
{
HasPathSum=true;
allpathvec.push_back(pathvec);
}
PreOrder(root->left,sum,path);
PreOrder(root->right,sum,path);
path-=root->val;
pathvec.pop_back();
}
}
vector<vector<int> > hasPathSum_recursivecall(TreeNode *root, int sum)
{
HasPathSum=false;
int path=0;
PreOrder(root,sum,path);
return allpathvec;
}