二元树中和为某一值的全部路径

二元树中和为某一值的全部路径

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

             近期在这里看到一道面试题,看了题目和作者的解答后,感觉真是强大。

     题目:输入一个整数和一棵二元树。从树的根结点開始往下訪问一直到叶结点所经过的全部结点形成一条路径。打印出和与输入整数相等的全部路径。

     比如输入整数22和例如以下二元树

                                      二元树中和为某一值的全部路径

    则打印出两条路径: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();} 

      细致看代码,你会发现,这样的方法遍历了解空间树,全部的叶子节点都会訪问到,

        假设二叉树是这种呢:

        二元树中和为某一值的全部路径

       依照这样的方法,20的两个孩子都会訪问到,可是,这在做无用功,由于,题目要求的是从根节点到叶子节点的路径和为22,当訪问到20的时候,路径和已是30了(大于22),再訪问20的孩子,路径和也会大于22,这样就没有必要再訪问20的孩子了。

       所以,应该避免这样的无效搜索,在遍历每一个节点的时候,先推断路径和是否大于目标值,假设大于的话,则不要遍历该节点的孩子,而且回溯。

      优化后的代码为:

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;	if(currentSum > expectedSum){  //推断路径和是否会超出目标值,超出则回溯		currentSum -= pTreeNode->m_nValue;		return;	}	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();}

        在原来的代码里添加�了例如以下代码:

if(currentSum > expectedSum){  //推断路径和是否会超出目标值,超出则回溯		currentSum -= pTreeNode->m_nValue;		return;	}

        剪去无效的子树,避免无效搜素,提高效率。

參考:

http://zhedahht.blog.163.com/blog/static/254111742007228357325/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118895.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 细说JDK动态代理的实现原理

    细说JDK动态代理的实现原理关于JDK的动态代理,最为人熟知的可能要数SpringAOP的实现,默认情况下,SpringAOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的代理使用CGLIB来实现。那么,什么是JDK的动态代理呢?JDK的动态代理,就是在程序运行的过程中,根据被代理的接口来动态生成代理类的class文件,并加载运行的过程。JDK从1.3开始支持动态代理。那么JDK是如何生成动态代理的

    2022年6月15日
    36
  • 四大审计费收费标准_四大 税务咨询收费

    四大审计费收费标准_四大 税务咨询收费“7年的心血和积累,说关就要关,说停就要停。没有人会甘心,但也早料到这一刻会突然到来。现在所能做的,唯有面对现实,准备好勇气,即使全部推倒从头再来,我们也绝不放弃。”1月22日,国内著名资源分享网站VeryCD的创始人黄一孟的这样一条微博牵动了不少用户的神经。用户们发现,VeryCD网站上的音乐频道已经悄然关闭,电影和电视剧频道也不再提供下载链接。坊间则风传VeryCD未取得广电总局的视听服务许

    2022年8月10日
    17
  • 手把手教你在Linux环境下安装Python3「建议收藏」

    在上一篇文章《手把手教你启用Win10的Linux子系统(超详细)》我们已经学了如何在Win10环境下装Linux子系统了,那么这一篇文章我们将学习如何在该Linux系统下安装Python3。首先是按Win+R键调出cmd命令窗口,然后输入输入bash指令进入Ubuntu系统,接着就可以进入正式的安装过程了。第一步、下载Python3输入下载命令:wgethttps://w…

    2022年4月17日
    40
  • 计算机技术与阅读,PISA2018阅读素养计算机化自适应测试的技术与方法探析

    计算机技术与阅读,PISA2018阅读素养计算机化自适应测试的技术与方法探析原标题:PISA2018阅读素养计算机化自适应测试的技术与方法探析摘要:PISA2018阅读素养的计算机化自适应测试采用核心阶段、阶段1和阶段2的3阶段自适应测试,题库设定有245道题目,组成45个测试单元,并将其组合成若干题组,用于不同阶段的测试。在路径设计上,为避免位置效应问题,除核心阶段→阶段1→阶段2的标准路径之外,还采用核心阶段→阶段2→阶段1的替代路径。PISA2018阅读素养计算机…

    2022年6月5日
    29
  • mysql longtext 查询_mysql中longtext存在大量数据时,会导致查询很慢?

    mysql longtext 查询_mysql中longtext存在大量数据时,会导致查询很慢?一个表,1.5w条数据,字段:id,name,content,last_update_timeid,自定义主键name,varchar类型content是longtext类型,last_update_time为datetime类型,不为空content当中是文本和代码等,平均长度在20k+。case1:selectid,namefromtorderbylast_update_tim…

    2022年5月14日
    47
  • Linux命令总结归纳

    Linux命令总结归纳Linux命令总结归纳

    2022年4月22日
    160

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号