二叉树中和为某一值的路径

题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶节点所经过的结点形成一条路径。二叉树的定义如下:

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
};

二叉树中我们最为熟悉操作莫过于各种遍历了,前序遍历(根左右),中序遍历(左根右),后序遍历(左右根)和层次遍历。而真正笔试题很少会直接考察二叉树的遍历的,而是需要我们会利用二叉树的遍历解决相关问题。最近因为这题思考良久,一直没得出合理的解决方案。期间反映出我对二叉树的操作还是很不熟悉!


对于上图和为20的路径包括{10,8,2},{10,6,3,1}和{10,6,4}。为了找出这些路径,我们来分析一下寻找流程,并尽量用上我们熟悉的二叉树遍历。由于需要的路径是从根节点到叶子节点打印,感觉上符合前序遍历!先走一遍,首先我们需要一个容器保存路径arr和一个遍历保存路径的节点和curNumber

1.遇到根节点10,将10放到路径中,curNumber = 10,此时路径为{10};

2.左结点不为空,访问左结点8,8保存到路径中,curNumber = 10+8 = 18,此时路径为{10,8};

3.左结点不为空,继续访问左结点5,5保存到路径中,curNumber = 18+5 = 23,此时路径为{10,8,5};

4.左右结点都为空,说明该节点为叶子结点,检查当前的路径值curNumber != 20,不是需要的路径不保存;

5.此时需要返回,删除路径中的末尾结点5,同时路径和减去末尾结点值5,回到结点8,curNumber = 18,此时结点路径为{10,8};

6.结点8的右子树不为空,访问右结点2,将2放到路径中,curNumber = 18+2 = 20,此时路径为{10,8,2};

7.结点2的左右子树都为空,结点2为叶子结点,当前的curNumber == 20,说明此时的路径为我需要的路径!将此时的路径保存起来(或者直接打印);当前路径中删除节点2,curNumber 减去当前节点的值2,返回到节点8;

8.继续将结点8从当前路径中删除,当前路径值减去8,则当前路径为{10},路径值为10;

9.访问结点10的右子树。。。

观察上述过程和前序遍历完全一致,只是中间多了路径的保存和路径值的判断。根据上述思想,我们可以得到下面的代码:

    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        vector<vector<int> > pathArr;<span style="white-space:pre">	</span>//保存所有的合法路径
        vector<int> currentPath;<span style="white-space:pre">	</span>//当前的路径
        int currentNumber = 0;<span style="white-space:pre">		</span>//当前的路径和
        if(root!=NULL)
        	FindValidPath(root,expectNumber,pathArr,currentPath,currentNumber);
        
        return pathArr;
    }
    
    void FindValidPath(TreeNode* root,int expectNumber,vector<vector<int>>& pathArr,
                       vector<int> &curPath,int& curNumber){
        if(root==NULL)
            return;
        
        curNumber += root->val;			//更新路径值
        curPath.push_back(root->val);	//更新路径
        
        if(root->left == NULL && root->right == NULL){	//如果是根节点,进行路径值的判断
            if(expectNumber == curNumber){
                pathArr.push_back(curPath);	//保存路径
            }
            curPath.pop_back();	//最后一个节点出栈
            curNumber -= root->val;
            return;
        }
        FindValidPath(root->left,expectNumber,pathArr,curPath,curNumber);	//处理左子树
        FindValidPath(root->right,expectNumber,pathArr,curPath,curNumber);	//处理右子树
        
        curPath.pop_back();		//对处理完的非叶子节点出栈,并更新当前路径和路径值
        curNumber -= root->val;
    }

最后推荐一个适合毕业生刷笔题练手的网站—— 牛客网(http://www.nowcoder.com/),本文讲的题目在该网站上也能 找到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值