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-名企面试官精讲典型编程题》-- 何海涛