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

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

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

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

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

     比如输入整数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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • HttpClient 3.1 文件上传

    HttpClient 3.1 文件上传

    2021年9月10日
    70
  • XXE漏洞学习[通俗易懂]

    XXE漏洞学习[通俗易懂]0x00什么是XML 1.定义XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。 2.文档结构XML文档结构包括XML声明、DTD文档类型…

    2022年5月23日
    34
  • c语言从入门到精通开发资源库_php源码建站∶一品资源

    c语言从入门到精通开发资源库_php源码建站∶一品资源NET学习从入门到精通100+源代码大放送 专辑中全部是源码资源,有基础学习源码,也有从网上需要购买的源码,现在全部免积分供大家学习参考专辑地址为:http://download.csdn.net/album/detail/3364具体包括    客户关系管理系统CRM源码        租房网(三层+MVC4)管理系统源        在线考试系统源码

    2022年9月15日
    0
  • Python生成可执行文件exe

    Python生成可执行文件exePython生成可执行文件exe一、安装pyinstallerpipinstallpyinstaller二、使用pyinstaller命令使用示例相对路径在程序目录中,运行命令pyinstallermyscript.py则可以在当前目录生成两个文件夹dist和build,exe文件在dist文件夹中。绝对路径在程序目录中,运行命令pyinstallerC:\mys…

    2025年5月26日
    0
  • Android Services Library_android freeware

    Android Services Library_android freeware对网络相关Api进行整理需要权限@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)获取网络当前网络manager.getActiveNetwork()动态网络回调manager.registerNetworkCallback网络的不同侧面新的Api中网络的不同关注面被放到的不同的对象中…

    2022年9月28日
    0
  • JAVA命令使用说明!

    JAVA命令使用说明!

    2021年4月27日
    138

发表回复

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

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