careercup-树与图 4.9

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);
}

方法二 完整代码:

#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;
}

方法三 完整代码:

#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;
}

时间: 2024-10-13 23:25:15

careercup-树与图 4.9的相关文章

D3树状图给指定特性的边特别显示颜色

D3作为前端图形显示的利器,功能之强,对底层技术细节要求相对比较多. 有一点,就是要理解其基本的数据和节点的匹配规则架构,即enter,update和exit原理,我前面的D3基础篇中有介绍过,不明白的可以再去研究下. 本篇博文,同样是在这个框架下,完成修改树状图中某两个节点之间的边用红色线条连接,实现表达特殊含义的目的. 背景故事: 微信朋友圈之间产品帖子相互转发,有些帖子转发后会有成交,只要有成交,则这个促成成交的节点及其之上的父节点都相应是有功劳的,这个轨迹需要用高亮的颜色表示(比如本例中

Android开源图表之树状图和饼状图的官方示例的整理

最近由于工作需要,所以就在github上搜了下关于chart的三方框架 官方地址https://github.com/PhilJay/MPAndroidChart 由于工作需要我这里整理了一份Eclipse版本的类库.(有需要要的留下邮箱) 这就是Code中的效果(树状图) 1 public class BarChartActivity extends Activity implements OnChartValueSelectedListener{ 2 3 private BarChart m

【 D3.js 入门系列 --- 9.5 】 树状图的制作

这一节学习树状图的制作.树状图的制作和集群图完全相同,经过这两种 layout 转换后的数据也很相似. 本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 树状图( Tree )通常用于表示层级.上下级.包含与被包含关系.树状图的制作和 9.4节集群图的制作 的代码几乎完全一样.不错,你没看错,几乎完全一样.那么为什么要把这两种图分开,它们有什么不同呢?先来看看对于同一组数据,它们的结果有什么不同.数据为: {

bzoj 4871: [Shoi2017]摧毁“树状图”

4871: [Shoi2017]摧毁“树状图” Time Limit: 25 Sec  Memory Limit: 512 MBSubmit: 53  Solved: 9[Submit][Status][Discuss] Description 自从上次神刀手帮助蚯蚓国增添了上千万人口(蚯口?),蚯蚓国发展得越来越繁荣了!最近,他们在地下发现了 一些神奇的纸张,经过仔细研究,居然是D国X市的超级计算机设计图纸!这台计算机叫做‘树状图’,由n个计算 节点与n1条可以双向通信的网线连接而成,所有计算

一款很好用的JQuery dtree树状图插件

一款很好用的JQuery dtree树状图插件 树状图  -dtree 由于他的节点设置思想不错,使连接数据库的数据库设计比较方便. 下载dtree资源包,引用一下dtree.css和dtree.js文件,然后编写节点就行了. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quo

Linux命令之pstree - 以树状图显示进程间的关系

本文链接:http://codingstandards.iteye.com/blog/842156   (转载请注明出处) 用途说明 pstree命令以树状图显示进程间的关系(display a tree of processes).ps命令可以显示当前正在运行的那些进程的信息,但是对于它们之间的关系却显示得不够清晰.在Linux系统中,系统调用fork可以创建子进程,通过子shell也可以创建子进程,Linux系统中进程之间的关系天生就是一棵树,树的根就是进程PID为1的init进程. 常用参

POJ 1436 Horizontally Visible Segments(线段树建图+枚举)

题目连接:http://poj.org/problem?id=1436 题意:给一些线段,每个线段有三个值y1, y2, x代表起点为(x, y1),终点为(x, y2)的线段.当从一个线段可以作水平线到另一个线段并且不穿过其他线段时,就称这两个线段时水平可见的.当三个线段可以两两水平可见,就称为形成一个线段三角.问:在这些线段中有多少个这样的线段三角? 分析:可以把每条线段看做是一个点,如果它和其他线段是水平可见的,就将这两个点相连,由于是无向图,就是你能看到我,我也能看到你,所以需要连接两次

D3树状图异步按需加载数据

D3.js这个绘图工具,功能强大不必多说,完全一个Data Driven Document的绘图工具,用户可以按照自己的数据以及希望实现的图形,随心所欲的绘图. 图形绘制,D3默认采用的是异步加载,但是,这里的异步加载,指的是一次性的将图形展示所需要的数据异步的方式加载到浏览器前端显示.主要有如下这两种方式: 1 d3.csv(url[[, row], callback]) 2 3 Creates a request for the CSV file at the specified url w

[Linux] Linux命令之pstree - 以树状图显示进程间的关系

转载自: http://codingstandards.iteye.com/blog/842156 pstree命令以树状图显示进程间的关系(display a tree of processes).ps命令可以显示当前正在运行的那些进程的信息,但是对于它们之间的关系却显示得不够清晰.在Linux系统中,系统调用fork可以创建子进程,通过子shell也可以创建子进程,Linux系统中进程之间的关系天生就是一棵树,树的根就是进程PID为1的init进程. 常用参数 格式:pstree 以树状图显

ArcGIS教程:树状图

摘要 构造可显示特征文件中连续合并类之间的属性距离的树示意图(树状图). 用法 · 输入特征文件必须采用预定的特征文件格式.特征文件可使用 Iso 聚类或创建特征工具来创建.该文件必须至少包含两个类.可通过扩展名 .gsg 来识别特征文件. · 树状图的输出是一个 ASCII 文本文件.该文件包含两部分:表和图形. 第一部分是以合并顺序显示各类对之间距离的表.第二部分是使用类的 ASCII 字符的图形表达,用来演示合并关系和等级.图形说明了特征文件中合并类对之间的相对距离,这些距离均基于统计得到