剑指offer 二叉树中和为某一值的路径(C++)

本文详细解析了如何寻找二叉树中节点值之和等于特定整数的所有路径,并通过代码实例展示了算法的具体实现过程,包括路径查找、判断及排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

解题思路

  • 设计一个函数,用vector存储根结点到各个叶子结点的路径,对每个路径进行判断,等于expectNumber,存入到二维vector中。
  • 设计一个函数,对每个一维数组中的元素和是否等于expectNumber进行判断。
  • 设计一个可以按照一维数组元素个数大小对二维数组中的一维数组进行排序的方法。

代码实现

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/

class Solution {
public: 
    bool IsEqualToExpectNumber(vector<int> &vnode, const int expectNumber) // 对每个一维数组中的元素和是否等于expectNumber进行判断
    {
        if(vnode.empty())
            return false;
        if(expectNumber <= 0)
            return false;
        return (expectNumber == accumulate(vnode.begin(), vnode.end(), 0));
        
    }
    
    void FindPathNode(TreeNode* &root, vector<vector<int> > &vnode, vector<int> &vtemp, const int expectNumber) // 打印根结点到叶子结点的路径,把符合题意的一维数组存到二维数组中
    {
        if (root)
        {
            vtemp.push_back(root->val);
            if (!root->left && !root->right)
            {
                if (IsEqualToExpectNumber(vtemp, expectNumber))
                {
                    vnode.push_back(vtemp);
                }
            }
            if (root->left)
            {
                FindPathNode(root->left, vnode, vtemp, expectNumber);
            }
            if (root->right)
            {
                FindPathNode(root->right, vnode, vtemp, expectNumber);
            }
        }
        if (vtemp.size())
        {
            vtemp.pop_back();
        }
    }
    void SortVector(vector<vector<int> > &vnode) //按照每个一维数组元素个数对二维数组中的一维数组进行排序
    {
        if(vnode.empty())
            return;
        for(int i = 0; i < vnode.size(); i++)
        {
            for(int j = i + 1; j < vnode.size(); j++)
            {
                if(vnode[i].size() < vnode[j].size())
                {
                    swap(vnode[i], vnode[j]); // swap可以直接用于两个vector的交换 但array类型的数组不可以
                }
            }
        }
    }

    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if(root == NULL)
            return {};
        vector<vector<int> > vnode;
        vector<int> vtemp;
        FindPathNode(root, vnode, vtemp, expectNumber);
        SortVector(vnode);
        return vnode;
    }
};

下面的代码是网上的:

class Solution {
public:
    vector<vector<int> > buffer;
    vector<int> tmp;
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if(root==NULL)
            return buffer;
        tmp.push_back(root->val);
        if((expectNumber-root->val)==0 && root->left==NULL && root->right==NULL)
            {
            buffer.push_back(tmp);
        }
        FindPath(root->left,expectNumber-root->val);
        FindPath(root->right,expectNumber-root->val);
        if(tmp.size()!=0)
            tmp.pop_back();
        return buffer;
    }
};

在VS2013上的运行

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<vector>
#include<numeric>
using namespace std;

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) : // 构造函数
		val(x), left(NULL), right(NULL) {
	}
};

void Print2ndVector(vector<vector<int> > &vnode) // 打印二维数组
{
	if (vnode.empty())
	{
		return;
	}
	vector<vector<int> >::iterator iter1 = vnode.begin();
	for (; iter1 != vnode.end(); iter1++)
	{
		for (vector<int>::iterator iter2 = iter1->begin(); iter2 != iter1->end(); iter2++)
		{
			cout << *iter2 << " ";
		}
		cout << endl;
	}
}

TreeNode* CreateTree() // 创建二叉树结点
{
	TreeNode* root = new TreeNode(5); //因为struct中的构造函数 初始化必须赋值
	TreeNode* left1 = new TreeNode(3);
	TreeNode* right1 = new TreeNode(7);
	root->right = left1; // 赋值问题 老是出错
	root->left = right1;
	TreeNode* left2 = new TreeNode(2);
	TreeNode* right2 = new TreeNode(4);
	left1->left = left2;
	left1->right = right2;
	return root;
}

bool IsEqualToExpectNumber(vector<int> vnode,const int expectNumber) // 判断路径和是否等于expectNumber
{
	if (vnode.empty())
		return false;
	if (expectNumber <= 0)
		return false;
	return (expectNumber == accumulate(vnode.begin(), vnode.end(), 0));//accumulate 是 #include<numeric>里面的

}

void FindPathNode(TreeNode* &root, vector<vector<int> > &vnode, vector<int> &vtemp, const int expectNumber) // 打印根结点到叶子结点的路径
{    // 打印总长度为12的路径
	if (root) 
	{
		vtemp.push_back(root->val);
		if (!root->left && !root->right)
		{
			if (IsEqualToExpectNumber(vtemp, expectNumber))
			{
				vnode.push_back(vtemp);
			}
		}
		if (root->left)
		{
			FindPathNode(root->left, vnode, vtemp, expectNumber);
		}
		if (root->right)
		{
			FindPathNode(root->right, vnode, vtemp, expectNumber);
		}
	}
	if (vtemp.size())
	{
		vtemp.pop_back();
	}
}

void SortVector(vector<vector<int> > &vnode) // 将按照结点数多少对二维数组中的每个一位数组进行排序
{
	if (vnode.empty())
		return;
	for (int i = 0; i < vnode.size(); i++)
	{
		for (int j = i + 1; j < vnode.size(); j++)
		{
			if (vnode[i].size() < vnode[j].size())
			{
				swap(vnode[i], vnode[j]); // swap可以直接用于两个vector的交换 但array类型的数组不可以
			}
		}
	}
}

void main()
{
	TreeNode* root = CreateTree(); // 创建二叉树结点
	vector<vector<int>> vnode; // 建立二维数组
	vector<int> vtemp; // 建立一维数组
	int expectNumber = 12; // 定义可以匹配的路径和
	FindPathNode(root, vnode, vtemp, expectNumber); // 打印总长度为12的路径

	Print2ndVector(vnode); // 打印二维数组
	cout << "排序之后的二维数组:" << endl;
	SortVector(vnode); // 调整 将按照结点数多少对二维数组中的每个一位数组进行排序
	Print2ndVector(vnode);// 打印二维数组

	system("pause");
	return;
}
/*
5 7
5 3 4
排序之后的二维数组:
5 3 4
5 7
请按任意键继续. . .
*/

该题目设计的知识点

1、打印二叉树根结点到所有叶子结点的路径

void AllPathFromRootToLeaves(TreeNode* &pRoot, vector<int> &vNode)
{
	if(pRoot)
	{
		vNode.push_back(pRoot->val);
		if(!pRoot->left && !pRoot->right)
			printVnode(vNode); // 打印vector中的元素
		if(pRoot->left)
			AllPathFromRootToLeaves(pRoot->left, vNode);
		if(pRoot->right)
			AllPathFromRootToLeaves(pRoot->right, vNode);
	}
	if(vNode.size())
		vNode.pop_back();
}

2、vector复制数据的方法

1、初始化时构造拷贝函数

vector<int> v1;
v1.push_back(1);
v1.push_back(2);

vector<int> v2(v1);

这种情况就是从将v1的元素复制到v2,v1不发生变化。

2、assign的用法

vector<int> v3;
v3.assign(v1.begin(), v1.end());

也是从将v1的元素复制到v3,v1不发生变化。

3、swap的用法(重点掌握)

vector<int> v4;
v4.swap(v1);

这种情况的结果是将v1中的数据全部转移到v4中,v1为空。

4、insert的用法

vector<int> v5;
v5.insert(v5.end(), v1.begin(), v2.end());

将v1中的数据全部复制插入到v5末端。

3、swap的用法简说

swap可以直接用于两个vector的交换 但array类型的数组不可以

swap(vnode[i], vnode[j]); 

一个VS2013上的例子:

void Print1Vector(vector<int> &vec)
{
	if (vec.empty())
	{
		return;
	}
	for (vector<int>::iterator iter = vec.begin(); iter != vec.end(); iter++)
	{
		cout << *iter << " ";
	}
	cout << endl;
}

void main()
{
	vector<int> a;
	a.push_back(1);
	a.push_back(2);
	a.push_back(3);
	vector<int> b;
	b.push_back(4);
	b.push_back(5);
	Print1Vector(a);
	Print1Vector(b);
	swap(a, b);
	cout << "交换后: " << endl;
	Print1Vector(a);
	Print1Vector(b);
	system("pause");
}
/*
1 2 3
4 5
交换后:
4 5
1 2 3
请按任意键继续. . .
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值