http://zhedahht.blog.163.com/blog/static/254111742007228357325/
题目:输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
例如输入整数22和如下二元树
10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。
二元树结点的数据结构定义为:
struct BinaryTreeNode // a node in the binary tree
{
int m_nValue; // value of node
BinaryTreeNode *m_pLeft; // left child of node
BinaryTreeNode *m_pRight; // right child of node
};
分析:这是百度的一道笔试题,考查对树这种基本数据结构以及递归函数的理解。
当访问到某一结点时,把该结点添加到路径上,并累加当前结点的值。如果当前结点为叶结点并且当前路径的和刚好等于输入的整数,则当前的路径符合要求,我们把它打印出来。如果当前结点不是叶结点,则继续访问它的子结点。当前结点访问结束后,递归函数将自动回到父结点。因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好是根结点到父结点的路径。我们不难看出保存路径的数据结构实际上是一个栈结构,因为路径要与递归调用状态一致,而递归调用本质就是一个压栈和出栈的过程。
参考代码:
///
// Find paths whose sum equal to expected sum
///
void FindPath
(
BinaryTreeNode* pTreeNode, // a node of binary tree
int expectedSum, // the expected sum
std::vector<int>& path, // a path from root to current node
int& currentSum // the sum of path
)
{
if(!pTreeNode)
return;
currentSum += pTreeNode->m_nValue;
path.push_back(pTreeNode->m_nValue);
// if the node is a leaf, and the sum is same as pre-defined,
// the path is what we want. print the path
bool isLeaf = (!pTreeNode->m_pLeft && !pTreeNode->m_pRight);
if(currentSum == expectedSum && isLeaf)
{
std::vector<int>::iterator iter = path.begin();
for(; iter != path.end(); ++ iter)
std::cout << *iter << '\t';
std::cout << std::endl;
}
// if the node is not a leaf, goto its children
if(pTreeNode->m_pLeft)
FindPath(pTreeNode->m_pLeft, expectedSum, path, currentSum);
if(pTreeNode->m_pRight)
FindPath(pTreeNode->m_pRight, expectedSum, path, currentSum);
// when we finish visiting a node and return to its parent node,
// we should delete this node from the path and
// minus the node's value from the current sum
currentSum -= pTreeNode->m_nValue;
path.pop_back();
}
本文已经收录到《剑指Offer——名企面试官精讲典型编程题》一书中,有改动,书中的分析讲解更加详细。欢迎关注。我在英文版博客http://codercareer.blogspot.com/2011/09/no-04-paths-with-specified-sum-in.html也讨论了这个题目,感兴趣的读者可以参考。
本题已被九度Online Judge系统收录,欢迎读者移步到http://ac.jobdu.com/hhtproblems.php在线测试自己的代码。
博主何海涛对本博客文章享有版权。网络转载请注明出处http://zhedahht.blog.163.com/。整理出版物请和作者联系。对解题思路有任何建议,欢迎在评论中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht与我讨论。谢谢。
以下是我自己的代码:
typedef struct BitNode
{
int elem;
struct BitNode *lchild,*rchild;
}BiTNode,*BiTree;
void CreateBiTree(BiTree& root)
{
int i;
scanf("%d",&i);
if(i)
{
root=(BiTree)malloc(sizeof(BiTNode));
root->lchild=NULL;
root->rchild=NULL;
root->elem=i;
CreateBiTree(root->lchild);
CreateBiTree(root->rchild);
}
else
root=NULL;
}
void Traverse(BiTree root)
{
if(root)
{
cout<<root->elem<<" ";
Traverse(root->lchild);
Traverse(root->rchild);
}
}
//自己的代码
int sum1=22;
void FindPath(BiTree root,std::vector<int> s,int cur)
{
if(cur>=sum1)
{
if(cur==sum1&&root->lchild==NULL&&root->rchild==NULL)
{
std::vector<int>::iterator iter=s.begin();
for(;iter!=s.end();iter++)
cout<<*iter<<" ";
cout<<endl;
}
}
else
{
if(root)
{
if(root->lchild){
s.push_back(root->lchild->elem);
FindPath(root->lchild,s,cur+root->lchild->elem);
s.pop_back();
}
if(root->rchild){
s.push_back(root->rchild->elem);
FindPath(root->rchild,s,cur+root->rchild->elem);
s.pop_back();
}
}
}
}
//博主的代码
void FindPath_1(BiTree root,std::vector<int> path,int currentSum)
{
if(!root)
return;
path.push_back(root->elem);
bool isLeaf = (NULL==root->lchild && NULL==root->rchild);
if(currentSum+root->elem == sum1 && isLeaf)
{
std::vector<int>::iterator iter = path.begin();
for(; iter != path.end(); ++ iter)
std::cout << *iter << '\t';
std::cout << std::endl;
}
if(root->lchild)
FindPath_1(root->lchild,path,currentSum+root->elem);
if(root->rchild)
FindPath_1(root->rchild,path,currentSum+root->elem);
path.pop_back();
}
int main()
{
BiTree root=NULL;
CreateBiTree(root);
std::vector<int> s;
s.push_back(root->elem);
FindPath(root,s,root->elem);
// cout<<endl;
std::vector<int> path;
FindPath_1(root,path,0);
return 0;
}