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

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

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

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

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

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


相关推荐

  • long long转string代码

    long long转string代码stringlltoString(longlongtimestamp){stringresult;ostringstreamss;ss<<timestamp;istringstreamis(ss.str());is>>result;returnresult;}包含头文件:#include…

    2022年5月14日
  • linux恢复硬盘初始状态,初始化Linux数据盘(fdisk)[通俗易懂]

    linux恢复硬盘初始状态,初始化Linux数据盘(fdisk)[通俗易懂]初始化Linux数据盘(fdisk)TkV南京数据恢复-西数科技:硬盘/手机/SSD数据恢复专家.025-8360863618913825606查看PDFTkV南京数据恢复-西数科技:硬盘/手机/SSD数据恢复专家.025-8360863618913825606分享操作场景本文以云服务器的操作系统为“CentOS7.464位”为例,采用fdisk分区工具为数据盘设置分区。TkV…

    2022年5月27日
  • android怎样换背景图片,手机怎么抠图换背景 安卓和iPhone一键抠图换背景教程

    android怎样换背景图片,手机怎么抠图换背景 安卓和iPhone一键抠图换背景教程原标题:手机怎么抠图换背景安卓和iPhone一键抠图换背景教程转自:电脑百事网果粉俱乐部原创平时很多小伙伴都喜欢拍照嗮图,而很多时候如果想要照片更美,抠图换背景会起到立竿见影的效果。那么,手机怎么抠图换背景?不少小伙伴苦于不懂PS抠图技术,总在羡慕别人。但其实很多人手机上分享的抠图照片都是通过一些APP就能够实现的,小白也可以轻松上手,下面“电脑百事网”干货来啦,教你如何借助APP,在安卓和i…

    2022年5月25日
  • ksh简介「建议收藏」

    ksh简介「建议收藏」–Start什么是Shell如果把Linux比作一个蛋,那么Shell就是蛋壳,我们需要通过Shell来使用系统。Shell的种类最早的Shell是BourneSh

    2022年8月2日
  • javascript百炼成仙 第一章 掌握JavaScript基础 1.2直接量

    javascript百炼成仙 第一章 掌握JavaScript基础 1.2直接量叶小凡的住处被安排在青山院西北角的一个房间里,虽不宽敞,倒也干净。叶小凡两眼露出振奋的眼神,随便吃了点乡亲们准备的干粮后,就立刻开始打坐修行。编程之修,重在积累,而非资质。资质虽然一样重要,可是后天的努力一样必不可少。这些道理,叶小凡还未上山之前,就已经熟知!因此,即便是资质平凡,只要肯下苦功,一样可以修得正果!叶小凡虽然甲等资质,可依然不骄不躁,开始从“JavaScript基础修炼要诀”第一页开始看起。修炼要诀第一章,直接量。编程世界,所谓直接量,就是明面上可以见到的数据值。常见的直接量有数字,小数,

    2022年6月11日
  • StretchDIBits用法

    StretchDIBits用法转自:http://blog.csdn.net/giantchen547792075/article/details/6996011StretchDIBits函数把DIB、JPEG、PNG图像中一矩形区域内的像素颜色数据复制到指定的目标矩形里。如果目标矩形大于源矩形,此函数将拉伸的行和列以适合目标矩形的颜色数据。如果目标矩形小于源矩形,则此函数使用指定的光栅操作压缩的行和列。(Note:整幅图像…

    2022年6月30日

发表回复

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

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