软件设计艺术大师基本功-二叉树-路径搜索-和为某一值的路径

Author: Frank

描述:

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

typedef struct BinaryTreeNode
{
    int data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BinaryTreeNode;

如下图所示的二叉树,如果需要找出所有路径和为22的路径,则会找出10-5-7和10-12两条路径。 路径总是从根结点开始,因此需要使用的是二叉树的前序遍历,通过递归的方式来实现即可。

在递归的作用下,会首先访问10,然后5,然后4,然后最深层的递归函数返回,然后访问7.  另外,上图所示的二叉树是没有指向父节点的指针的,访问到某一个结点时,我们并不知道其前面经过了多少结点,从而需要在访问过程中将经过的结点记录下来。例如访问到结点4时,路径中记录了10-5-4,由于4是叶子,这时判断路径和是否是22,然后,将4从路径记录中剔除(每次返回父节点时,都需要将当前的叶子结点从记录中删除),将下一个被访问的结点7加入路径。

最后访问的是12,在遍历这个结点之前,需要先经过结点5回到10,同样地每一次从子节点返回至父节点的时候我们在记录的路径中删除子节点。最后从10到达12的时候,路径两个结点10,12。

至于路径的存储,需要使用的是vector。

代码:(递归调用的过程可以逐层在纸上画出来理解)

 
void FindPath(BinaryTreeNode* root, int expectedSum, std::vector<int>& path, int& currentSum)
{
	currentSum += root->data;
	path.push_back(root->data);
	//判断当前节点是否是叶子,如果是则判断当前保存的路径之和是否是expectedSum。
	bool isLeaf = (NULL == root->left && NULL == root->right);
	if (isLeaf && (currentSum == expectedSum))
	{
		//printf("s%","A path is found\n");
		std::vector<int>::iterator iter = path.begin();
		for (; iter != path.end(); ++iter)
			printf("%d \t", *iter);
		printf("\n");
	}
	//继续遍历当前节点的左右子节点
	if (NULL != root->left)
		FindPath(root->left, expectedSum, path, currentSum);
	if (NULL != root->right)
		FindPath(root->right, expectedSum, path, currentSum);
	//返回父节点之前,将当前节点从路径中删除:
	currentSum -= root->data;
	path.pop_back();
	return;
}
void Prepare(BinaryTreeNode* root, int expectedSum)
{
	if (root == NULL)
		return;
	std::vector<int> path;
	int currentSum = 0;
	FindPath(root, expectedSum, path, currentSum);
}
//--------------------------------------------测试代码:----------------------------------------------------------
#include "stdafx.h"
#include <vector>
using namespace std;

BinaryTreeNode* CreatBinaryNode(int data, BinaryTreeNode* left, BinaryTreeNode* right)
{
	BinaryTreeNode* temp = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
	temp->data = data; temp->left = left; temp->right = right;
	return temp;
}

int main()
{
       //creat binary tree
	BinaryTreeNode* root = NULL;
        root = CreatBinaryNode(10,NULL,NULL);
	root->left= CreatBinaryNode(5, NULL, NULL);
	root->right = CreatBinaryNode(12, NULL, NULL);
	root->left->left= CreatBinaryNode(4, NULL, NULL);
	root->left->right = CreatBinaryNode(7, NULL, NULL);

	Prepare( root, 22);
	getchar();
	return 0;
}

2021.0327的练习:

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

struct Node {
	Node(int val=0):mVal(val),mLeft(nullptr),mRight(nullptr) {

	}

	int mVal;
	Node* mLeft;
	Node* mRight;
};

void recuFind(Node* root, int& accuSum, vector<int>& cachVector, const int targetSum) {
	if (!root) {
		return;
	}
	int currVal = root->mVal;
	accuSum += currVal;
	cachVector.push_back(currVal);
	if (root->mLeft) {
		recuFind(root->mLeft, accuSum, cachVector,targetSum);
	}
	if (root->mRight) {
		recuFind(root->mRight, accuSum, cachVector, targetSum);
	}
	if (!root->mLeft && !root->mRight) {
		if (targetSum == accuSum) {
			cout << "Founded path:";
			for (const auto& it : cachVector) {
				cout << it <<"  ";
			}
			cout << endl;
		}
	}
	accuSum -= currVal;
	cachVector.pop_back();//原来vector也有这个功能啊!
}

int main() {
	Node* root = new Node(1);
	root->mLeft = new Node(2);
	root->mRight = new Node(3);

	root->mLeft->mLeft = new Node(1);
	root->mLeft->mRight = new Node(1);

	vector<int> cachVec;
	int accuSum = 0;
	recuFind(root, accuSum, cachVec, 4);
}

 

 

 

 

 

 

 

 

参考:

 

《剑指offer-名企面试官精讲典型编程题》-- 何海涛

 

 

 

 

题目要求:给定一个二叉树和一个整数target,找出所有从根节点到叶子节点路径之和等于target的路径。 解题思路:可以使用深度优先搜索(DFS)的方法来解决该问题。首先定义一个辅助函数来进行递归搜索,该辅助函数的参数包括当前节点、当前路径、当前路径的和以及目标和。在搜索过程中,需要维护一个数组来保存当前节点到根节点的路径搜索过程如下: 1. 如果当前节点为空,则返回。 2. 将当前节点的值添加到当前路径中。 3. 将当前节点的值累加到当前路径的和中。 4. 如果当前节点是叶子节点,且当前路径的和等于目标和,则将当前路径添加到结果中。 5. 递归搜索当前节点的左子树和右子树,并传递更新后的当前路径和当前路径的和。 最后,在主函数中调用辅助函数,并返回结果即可。 以下是题目的完整代码实现: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def pathSum(root, target): def dfs(node, path, path_sum, target, res): if not node: return path.append(node.val) path_sum += node.val if not node.left and not node.right: # 当前节点是叶子节点 if path_sum == target: res.append(path[:]) # 注意需要复制一份path,否则会出现问题 dfs(node.left, path, path_sum, target, res) dfs(node.right, path, path_sum, target, res) path.pop() # 回溯到父节点,去掉当前节点 path_sum -= node.val res = [] dfs(root, [], 0, target, res) return res ``` 这样就能找出所有满足路径和等于目标和的路径了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

First Snowflakes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值