zoukankan      html  css  js  c++  java
  • 二元树中和为某一值的所有路径

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

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

         例如输入整数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 << '	';
               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 << '	';
    		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/





    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    这个 bug 让我更加理解 Spring 单例了
    SpringBoot
    codeblocks笔记
    https://docs.platformio.org/en/latest/boards/index.html
    外部存储的烧写
    嵌入式AI
    python的一些库
    语音芯片及解决方案
    神奇的调试值“DEADBEEF”
    【12月】+我与rt_thread的“江湖恩怨”
  • 原文地址:https://www.cnblogs.com/Rex7/p/4752569.html
Copyright © 2011-2022 走看看