且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

careercup-树与图 4.9

更新时间:2022-08-22 08:32:11

4.9 给定一颗二叉树,其中每个结点都含有一个数值。设计一个算法,打印结点数值总和等于某个给定值的所有路径。注意,路径不一定非得从二叉树的根节点或叶子节点开始或结束。

 

类似于leetcode:Path Sum II

C++实现代码:(使用了双重的递归)对于不含有parent指针域时。

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

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

class Solution
{
public:
    vector<vector<int> > path;
    vector<vector<int> > pathSum(TreeNode *root, int sum)
    {
        vector<int> tmp;
        hasPathSum(root,sum,tmp);
        //改变开始的节点,不一定要从根结点开始,遍历从每一个节点开始
        if(root->left)
            pathSum(root->left,sum);
        if(root->right)
            pathSum(root->right,sum);
        return path;
    }
    void hasPathSum(TreeNode *root, int sum,vector<int> tmp)
    {
        if(root==NULL)
            return;
        tmp.push_back(root->val);
        //改变结束的地方,不一定要到叶子节点
        if((sum-root->val)==0)
        {
            path.push_back(tmp);
        }
        if(root->left)
            hasPathSum(root->left,sum-root->val,tmp);
        if(root->right)
            hasPathSum(root->right,sum-root->val,tmp);
    }
    void createTree(TreeNode *&root)
    {
        int i;
        cin>>i;
        if(i!=0)
        {
            root=new TreeNode(i);
            if(root==NULL)
                return;
            createTree(root->left);
            createTree(root->right);
        }
    }
};
int main()
{
    Solution s;
    TreeNode *root;
    s.createTree(root);
    vector<vector<int> > path=s.pathSum(root,6);
    for(auto a:path)
    {
        for(auto v:a)
            cout<<v<<" ";
        cout<<endl;
    }
}

 方法二:如果结点中包含指向父亲结点的指针,那么,只需要去遍历这棵二叉树, 然后从每个结点开始,不断地去累加上它父亲结点的值直到父亲结点为空(这个具有唯一性, 因为每个结点都只有一个父亲结点。也正因为这个唯一性, 可以不另外开额外的空间来保存路径),如果等于给定的值sum,则打印输出。

实现的方法:

void find_sum(Node* head, int sum){
    if(head == NULL) return;
    Node *no = head;
    int tmp = 0;
    for(int i=1; no!=NULL; ++i){
        tmp += no->key;
        if(tmp == sum)
            print(head, i);
        no = no->parent;
    }
    find_sum(head->lchild, sum);
    find_sum(head->rchild, sum);
}

打印输出时,只需要提供当前结点的指针,及累加的层数即可。然后从当前结点开始, 不断保存其父亲结点的值(包含当前结点)直到达到累加层数,然后逆序输出即可。

代码如下:

void print(Node* head, int level){
    vector<int> v;
    for(int i=0; i<level; ++i){
        v.push_back(head->key);
        head = head->parent;
    }
    while(!v.empty()){
        cout<<v.back()<<" ";
        v.pop_back();
    }
    cout<<endl;
}

方法三:如果结点中不包含指向父亲结点的指针,则在二叉树从上向下查找路径的过程中, 需要为每一次的路径保存中间结果,累加求和仍然是从下至上的,对应到保存路径的数组, 即是从数组的后面开始累加的,这样能保证遍历到每一条路径。

代码如下:

void print2(vector<int> v, int level){
    for(int i=level; i<v.size(); ++i)
        cout<<v.at(i)<<" ";
    cout<<endl;
}
void find_sum2(Node* head, int sum, vector<int> v, int level){
    if(head == NULL) return;
    v.push_back(head->key);
    int tmp = 0;
    for(int i=level; i>-1; --i){
        tmp += v.at(i);
        if(tmp == sum)
            print2(v, i);
    }
    vector<int> v1(v), v2(v);
    find_sum2(head->lchild, sum, v1, level+1);
    find_sum2(head->rchild, sum, v2, level+1);
}

方法二 完整代码:

careercup-树与图 4.9careercup-树与图 4.9
#include<iostream>
#include<new>
#include<map>
#include<vector>
using namespace std;

struct BinarySearchTree
{
    int elem;
    BinarySearchTree *parent;
    BinarySearchTree *left;
    BinarySearchTree *right;
    BinarySearchTree(int x):elem(x),parent(NULL),left(NULL),right(NULL) {}
};

void insert(BinarySearchTree *&root,int z)
{
    BinarySearchTree *y=new BinarySearchTree(z);
    if(root==NULL)
    {
        root=y;
        return;
    }
    else if(root->left==NULL&&z<root->elem)
    {
        root->left=y;
        y->parent=root;
        return;
    }
    else if(root->right==NULL&&z>root->elem)
    {
        root->right=y;
        y->parent=root;
        return;
    }
    if(z<root->elem)
        insert(root->left,z);
    else
        insert(root->right,z);
}

void createBST(BinarySearchTree *&root)
{
    int arr[10]= {10,4,6,1,8,3,0,7,2,9};
    for(auto a:arr)
        insert(root,a);
}

//使用level的原因就是因为,不一定要到根,只有根的父节点为NULL
void print(BinarySearchTree *head,int level)
{
    vector<int> vec;
    for(int i=0;i<level;++i)
    {
        vec.push_back(head->elem);
        head=head->parent;
    }
    while(!vec.empty())
    {
        cout<<vec.back()<<" ";
        vec.pop_back();
    }
    cout<<endl;
}
//root选择的是当前结束的节点,也就是从下往上开始最下面的节点,而node是往上找到的刚好满足的最后一个结点,root是在不断加深的
void find_sum(BinarySearchTree *root,int sum)
{
    if(root==NULL)
        return;
    BinarySearchTree *node=root;
    int tmp=0;
    for(int i=1;node!=NULL;++i)
    {
        tmp+=node->elem;
        if(tmp==sum)
            print(root,i);
        node=node->parent;
    }
    find_sum(root->left,sum);
    find_sum(root->right,sum);
}
int main()
{
    BinarySearchTree *root=NULL;
    createBST(root);
    cout<<"find sum is: "<<endl;
    find_sum(root,10);
    return 0;
}
View Code

方法三 完整代码:

careercup-树与图 4.9careercup-树与图 4.9
#include<iostream>
#include<new>
#include<map>
#include<vector>
using namespace std;

struct BinarySearchTree
{
    int elem;
    BinarySearchTree *parent;
    BinarySearchTree *left;
    BinarySearchTree *right;
    BinarySearchTree(int x):elem(x),parent(NULL),left(NULL),right(NULL) {}
};

void insert(BinarySearchTree *&root,int z)
{
    BinarySearchTree *y=new BinarySearchTree(z);
    if(root==NULL)
    {
        root=y;
        return;
    }
    else if(root->left==NULL&&z<root->elem)
    {
        root->left=y;
        y->parent=root;
        return;
    }
    else if(root->right==NULL&&z>root->elem)
    {
        root->right=y;
        y->parent=root;
        return;
    }
    if(z<root->elem)
        insert(root->left,z);
    else
        insert(root->right,z);
}

void createBST(BinarySearchTree *&root)
{
    int arr[10]= {10,4,6,1,8,3,0,7,2,9};
    for(auto a:arr)
        insert(root,a);
}

//使用level记录选择v中的从哪个下标开始相加
void print(vector<int> v,int level)
{
    for(int i=level;i<v.size();++i)
        cout<<v[i]<<" ";
    cout<<endl;
}
//root开始,将当前层的值加入v中
void find_sum(BinarySearchTree *root,int sum,vector<int> v,int level)
{
    if(root==NULL)
        return;
    v.push_back(root->elem);
    int tmp=0;
    for(int i=level;i>-1;--i)
    {
        tmp+=v[i];
        if(tmp==sum)
            print(v,i);
    }
    //每一层将当前层的结点的值放入v中,由于不是传递的引用,所以同一层放入v中的值不会影响,从root结点开始保存每一层的
    find_sum(root->left,sum,v,level+1);
    find_sum(root->right,sum,v,level+1);
}
int main()
{
    BinarySearchTree *root=NULL;
    createBST(root);
    vector<int> v;
    cout<<"find sum is: "<<endl;
    find_sum(root,10,v,0);
    return 0;
}
View Code

careercup-树与图 4.9