剑指offer面试题25-二叉树中和韦某一值的路径

question:给定一颗二叉树,一个值。我们希望输出和为该值的所有路径。

假设树的结构如下


思路:使用一个基于先序遍历的递归过程来遍历树中每个点一次,每遍历一个点就要获得从根节点到被访问的点的累加和,并保存从根节点到当前点的路径。然后进行判断,

case1如果当前点的左右孩子都为空(叶子节点)并且累加和等于我们期望的和,那么就打印出路径;

case2如果左孩子为空,递归到最孩子;

case3如果右孩子为空,递归到右孩子;

case4如果是叶子并且当前和不等于期望和,网上回退

试下代码:

参数为值传递的代码

#include<vector>
#include<iostream>
using namespace std;
typedef struct BinaryTreeNode
{
	int data;
	struct BinaryTreeNode *lchild;
	struct BinaryTreeNode *rchild;
}*BinTreeRoot;


void createTree1(BinaryTreeNode *&root)
{
	root = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	root->data = 8;
	root->lchild = NULL;
	root->rchild = NULL;

	BinaryTreeNode *p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 8;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 7;
	p->lchild = NULL;
	p->rchild = NULL;
	root->rchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 9;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->lchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 2;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->rchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 4;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->rchild->lchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 7;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->rchild->rchild = p;
}


void findPath(BinaryTreeNode *root, int expectedSum, int curSum, vector<int>path)
{
	if (root == NULL)
		return;
	curSum += root->data;
	path.push_back(root->data);
	if (root->lchild == NULL && root->rchild == NULL && curSum == expectedSum)
	{
		for (auto iter = path.begin(); iter != path.end();  ++iter)
		{
			if (iter + 1 == path.end())
			{
				cout << *iter << endl;
			}
			else
			{
				cout << *iter << "->";
			}
		}
	}
	if (root->lchild != NULL)
	{
		findPath(root->lchild, expectedSum, curSum, path);
	}
	if (root->rchild != NULL)
	{
		findPath(root->rchild, expectedSum, curSum, path);
	}
//	curSum -= root->data;
//	path.pop_back();
}


int main()
{
	BinaryTreeNode *root = NULL;
	createTree1(root);
	if (root == NULL)
	{
		cout << "the tree is empty!" << endl;
		return 0;
	}
	int curSum = 0;//存放从根节点到当前节点的路径和
	int expectedSum;//我们期待的值
	cin >> expectedSum;
	vector<int>path;//存放路径
	findPath(root, expectedSum, curSum, path);
	return 0;
}
注意:在这个代码中存放累加和curSum、路径path的变量都是使用的值传递,而不是引用传递。因为该方法是一个递归的过程,在每一个递归栈中都有一个临时变量curSum和path。如果递归返回到上一层时,本次计算的没有影响。相反,如果使用了引用传递的,需要手动修改数据的值:

参数为引用传递的代码:

#include<vector>
#include<iostream>
using namespace std;
typedef struct BinaryTreeNode
{
	int data;
	struct BinaryTreeNode *lchild;
	struct BinaryTreeNode *rchild;
}*BinTreeRoot;


void createTree1(BinaryTreeNode *&root)
{
	root = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	root->data = 8;
	root->lchild = NULL;
	root->rchild = NULL;

	BinaryTreeNode *p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 8;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 7;
	p->lchild = NULL;
	p->rchild = NULL;
	root->rchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 9;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->lchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 2;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->rchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 4;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->rchild->lchild = p;

	p = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
	p->data = 7;
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild->rchild->rchild = p;
}


void findPath(BinaryTreeNode *root, int expectedSum, int &curSum, vector<int>&path)//引用传递
{
	if (root == NULL)
		return;
	curSum += root->data;
	path.push_back(root->data);
	if (root->lchild == NULL && root->rchild == NULL && curSum == expectedSum)
	{
		for (auto iter = path.begin(); iter != path.end();  ++iter)
		{
			if (iter + 1 == path.end())
			{
				cout << *iter << endl;
			}
			else
			{
				cout << *iter << "->";
			}
		}
	}
	if (root->lchild != NULL)
	{
		findPath(root->lchild, expectedSum, curSum, path);
	}
	if (root->rchild != NULL)
	{
		findPath(root->rchild, expectedSum, curSum, path);
	}
	curSum -= root->data;//curSum和path是引用传递,所以如果递归返回到上一层的时候,需要减去本次的累加
	path.pop_back();
}


int main()
{
	BinaryTreeNode *root = NULL;
	createTree1(root);
	if (root == NULL)
	{
		cout << "the tree is empty!" << endl;
		return 0;
	}
	int curSum = 0;//存放从根节点到当前节点的路径和
	int expectedSum;//我们期待的值
	cin >> expectedSum;
	vector<int>path;//存放路径
	findPath(root, expectedSum, curSum, path);
	return 0;
}

过程:假设我们希望输出和为25的所有路径;

设定以下变量:int curSum = 0;//存放当前累加和

                         int expectedSum = 25;//期待和

                         vector<int>path;//用于存放路径

                         BinaryTreeNode *root;//指向树中根节点的指针

(1)首先从根节点出发,curSum = 8,并且不是叶子节点,并且值不为35。


(2)由于是基于先序遍历的,接下来我们访问左孩子,累加和为8+8=16,仍然不是叶子节点。


(3)再访问8的右孩子9,累加和为25,并且是叶子节点。此时打印出路径


路径为8->8->9

(4)使用一个递归的过程,然后向上回退到节点8,并且访问8的右孩子2


(5)访问2的左孩子4,此时累加和为22.


(6)当前访问到的点4是一个叶子节点,并且累加和为22,不是我们所期待的,所以向上回退到2,并且访问2的右孩子7,此时7是叶子节点。并且和为25,所以满足要求,打印出路径


路径为:8->8->2->7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值