面试经典(17)--二叉树中和为某一值的路径

题目描述:输入一棵二叉树和一个整数(假如为N),打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶子节点所经过的节点形成一条路径。

例如 输入整数22和如下二元树
      10   
      / \   
     5  12   
      / \    
      4    7
则打印出两条路径:10, 12和10, 5, 7。

分析与解法:

使用前序遍历,因为要求所有的满足条件的路径,必须遍历完整棵树。我们使用vector容器来保存路径,维护保存路径和的变量curSum,第一次遍历到一个节点就加入vector,curSum加上当前节点的值,如果当前curSum大于等于指定的N,并且当前节点不是叶子节点,那么要调用pop_back。我们还需要更深入的考虑一下退出条件,发现只要从一个节点的左右子树返回就要弹出节点,因为前序遍历当中,一个节点的左右子树返回意味着经过当前节点的所有路径我们都遍历过了,所以自然要pop_back当前节点。比如10->5->4,当前和不满足条件,我们要回退,这个时候要pop_back弹出4。然后进入5的右子树,找到10->5->7满足条件,回退的时候我们要pop_back弹出7。由于5的左右子树全都返回,所以我们也要pop_back弹出5。

输出条件:路径和满足条件,并且是叶子节点。

另外再分析下curSum是要定义为局部变量还是放到参数里面。因为更深层次的子树需要知道这个值,所以放到参数里面。定义为int类型还是int&(c里面当然用int*代替啦)类型?其实无所谓,这个对算法正确性没有影响。

根据上述分析,代码如下:

struct Node
{
	Node* m_pLeft;
	Node* m_pRight;
	int m_value;
};

void allPath(Node *pRoot,vector<int>& v,int curSum,int expectedSum)
{
	if(pRoot==NULL)
	{
		return;
	}
	v.push_back(pRoot->m_value);
	curSum+=pRoot->m_value;
	//当前路径和大于等于指定值,且不是叶子节点
	if(curSum>=expectedSum && (pRoot->m_pLeft || pRoot->m_pRight))
	{
		v.pop_back();
		curSum-=pRoot->m_value;
	}

	//输出条件
	if(curSum==expectedSum && pRoot->m_pLeft==NULL && pRoot->m_pRight==NULL)
	{
		for(int i=0;i<v.size();i++)
			cout<<v[i]<<" ";
		cout<<endl;
	}
	//if判定条件可以不加,加上只是少一层递归而已,当然最好加上啦
	if(pRoot->m_pLeft)
		allPath(pRoot->m_pLeft,v,curSum,expectedSum);
	if(pRoot->m_pRight);
		allPath(pRoot->m_pRight,v,curSum,expectedSum);
	v.pop_back();
	curSum-=pRoot->m_value;
}


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值