构造数组的MaxTree

【说明】:

  本文是左程云老师所著的《程序员面试代码指南》第一章中“构造数组的MaxTree”这一题目的C++复现。

  本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

  感谢左程云老师的支持。

【题目】:

  定义二叉树节点如下:

class Node
{
public:
    Node(int data)
    {
        value = data;
        left = NULL;
        right = NULL;
    }
public:
    int value;
    Node *left;
    Node *right;
};

  一个数组的 MaxTree 定义如下:

  •   数组必须没有重复元素;
  •   MaxTree 是一棵二叉树,数组的每一个值对应一个二叉树节点;
  •   包括 MaxTree 树在内且在其中一的每一棵子树上,值最大的节点都是树的头。

  给定一个没有重复元素的数组 arr,写出生成这个数组的 MaxTree 的函数,要求如果数组长度为 N,则时间复杂度为 O(N),额外空间复杂度为 O(N)。

【思路】:

  利用栈找到每个数左右两边第一个比它大的数,并且用hash_map保存。(估计这样说大家都不明白,大家可以看原书,或者分析代码喽)

【编译环境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

【实现】:

  实现及测试代码:

#include <sstream>

using namespace std;
using namespace __gnu_cxx;

class Node
{
public:
    Node(int data)
    {
        value = data;
        left = NULL;
        right = NULL;
    }
public:
    int value;
    Node *left;
    Node *right;
};

/*
 *函数说明:利用hash_map分别为每一个数的左边和右边第一个最大值(序号)设定关联
 *输入参数:s为存放数组序号的栈;map为待建好的映射表
 *输出参数:s为存放数组序号的栈;map为整理好的映射表
 *返回值:
 */
void popStackSetMap(stack<int> &s,hash_map<int,string> &map)
{
    int tmp = s.top();
    s.pop();
    stringstream ss;
    string str;
    if(s.empty())
    {
        map[tmp] = str;
    }
    else
    {
        ss << s.top();
        ss >> str;
        map[tmp] = str;        //序号对应序号的关系
    }
    return ;
}

Node* getMaxTree(int a[],int len)
{
    stack<int> s;
    hash_map<int,string> lBigMap;
    //为数组内的每个数据分别对应一个左端第一个最大值,没有则为空
    for(int i=0; i<len; i++)
    {
        while(!s.empty() && a[s.top()] < a[i])
            popStackSetMap(s,lBigMap);
        s.push(i);    //注意,这里保存的是数组序号,而不是数组值
    }
    while(!s.empty())
        popStackSetMap(s,lBigMap);
    //为数组内的每个数据分别对应一个右端第一个最大值,没有则为空
    hash_map<int,string> rBigMap;
    for(int i=len-1; i>=0; i--)
    {
        while(!s.empty() && a[s.top()] < a[i])
            popStackSetMap(s,rBigMap);
        s.push(i);    //注意,这里保存的是数组序号,而不是数组值
    }
    while(!s.empty())
        popStackSetMap(s,rBigMap);
    //构造Node数组
    Node* nArr[len];
    for(int i=0;i<len;i++)
    {
        nArr[i] = new Node(a[i]);
    }
    //构造Node的MaxTree
    Node *head = NULL;
    for(int i=0;i<len;i++)
    {
        //调试代码
        //cout << "nArr[" << i << "]->value = " << nArr[i]->value << endl;
        //cout << "lBigMap = " << lBigMap[i] << endl;
        //cout << "rBigMap = " << rBigMap[i] << endl;

        string ls = lBigMap[i];
        string rs = rBigMap[i];
        if(ls.empty() && rs.empty())
        {
            head = nArr[i];
        }
        else if(ls.empty())
        {
            stringstream ss(rs);
            int rID;
            ss >> rID;
            if(NULL == nArr[rID]->left)
                nArr[rID]->left = nArr[i];
            else
                nArr[rID]->right = nArr[i];
        }
        else if(rs.empty())
        {
            stringstream ss(ls);
            int lID;
            ss >> lID;
            if(NULL == nArr[lID]->left)
                nArr[lID]->left = nArr[i];
            else
                nArr[lID]->right = nArr[i];
        }
        else
        {
            stringstream lss(ls);
            int lID;
            lss >> lID;

            stringstream rss(rs);
            int rID;
            rss >> rID;

            int pID = a[lID] < a[rID] ? lID : rID;

            if(NULL == nArr[pID]->left)
                nArr[pID]->left = nArr[i];
            else
                nArr[pID]->right = nArr[i];
        }
    }
    return head;
}

int main()
{
    int a[] = {3,4,5,1,2};
    Node *head = getMaxTree(a,5);
    Node *left = head->left;
    Node *right = head->right;
    cout << "head->value = "<< head->value << endl;
    cout << head->value <<"->left->value = "<< left->value << endl;
    cout << head->value <<"->right->value = "<< right->value << endl;
    if(NULL != left->left)
        cout << left->value << "->left->value = " << left->left->value << endl;
    else
        cout << left->value << "->left is empty!" << endl;

    if(NULL != left->right)
        cout << left->value << "->right->value = " << left->right->value << endl;
    else
        cout << left->value << "->right is empty!" << endl;

    if(NULL != right->left)
        cout << right->value << "->left->value = " << right->left->value << endl;
    else
        cout << right->value << "->left is empty!" << endl;

    if(NULL != right->right)
        cout << right->value << "->right->value = " << right->right->value << endl;
    else
        cout << right->value << "->right is empty!" << endl;
    return 0;
}

【说明】

  1、hash_map并不属于标准的STL,但是大部分的开发环境已经将其实现。在GCC中也可直接使用,但是需要声明命名空间为 __gnu_cxx;

  2、C++中的hash_map的使用自定义的类型时,需要在类中实现hash函数和等于比较函数,所以我使用了string作为替代;

  3、在string与int类型的互换中,我使用了stringstream这一辅助类型。

  4、关键的思路还是参考了左程云老师提出的思路,具体实现有些差别,小伙伴们可以自行查看。

  5、hash_map使用方法的参考文章:

      C++ STL中哈希表 hash_map介绍

      hash_map使用自定义类型做主键

  6、测试代码未使用二叉树的遍历算法,大家就凑合着看看吧。^_^  ^_^   ^_^

注:

  转载请注明出处;

  转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

时间: 2024-11-07 02:27:56

构造数组的MaxTree的相关文章

《程序员面试指南》第一章 栈和队列 构造数组的MaxTree

题目 给出一个无重复元素的数组,构造此数组的MaxTree, java代码 /** * @Description: 构造数组的MaxTree * @Author: lizhouwei * @CreateDate: 2018/4/5 22:16 * @Modify by: * @ModifyDate: */ public class Chapter1_8 { public Node getMaxTree(int[] arr) { if (arr == null) { return null; }

算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序

接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public int value; public Node left; public Node right; public Node(int data){ this.value=data; } } 一个数组的MaxTree定义如下: ◆ 数组必须没有重复元素 ◆ MaxTree是一颗二叉树,数组的每一个值对应一

左神算法进阶班3_1构造数组的MaxTree

题目 一个数组的MaxTree定义: 数组必须没有重复元素 MaxTree是一棵二叉树,数组的每一个值对应一个二叉树节点 包括MaxTree树在内且在其中的每一棵子树上,值最大的节点都是树的头 给定一个没有重复元素的数组arr,写出生成这个数组的MaxTree的函数,要求如果数组长度为N,则时间负责度为O(N).额外空间负责度为O(N). 实现思路 将数组按照大根堆进行排序 然后直接按照大根堆进行构造一颗二叉树即可. 使用单调栈 通过使用单调栈,将数组中中所有数的左右比他大的数记录下来 当某个数

NumPy常用函数(一)——构造数组函数及代码示例

NumPy是Python的一个科学计算的基本模块.它是一个Python库,提供了一个多维数组对象,各种衍生对象(如屏蔽数组和矩阵),以及用于数组,数学,逻辑,形状操纵,排序,选择,I/O等快速操作的各种例程 离散傅里叶变换,基本线性代数,基本统计运算,随机模拟等等. 本文主要列出构造数组常用的函数或者成为子模块 一.0-1数组 empty(shape [,dtype,order])                      返回给定形状和类型的新数组,而不初始化条目. empty_like(a

给定数组a[N]构造数组b[N]

转自:http://blog.csdn.net/wumuzi520/article/details/7841280 给定一个数组a[N],我们希望构造数组b [N], 其中b[j]=a[0]*a[1]…a[N-1] / a[j], 在构造过程中,不允许使用除法:要求O(1)空间复杂度和O(n)的时间复杂度: 除遍历计数器与a[N] b[N]外,不可使用新的变量 (包括栈临时变量.堆空间和全局静态变量等) 解析:设b[0]=1 由b[i]=b[i-1]*a[i-1]可得 b[1] = a[0] b

已知一个数组a[N]来构造数组b[N]的有趣算法题

给定一个数组a[N],我们希望构造数组b[N],其中b[i]=a[0]*a[1]*...*a[N-1]/a[i].在构造过程要求满足:1.不使用除法:2.O(1)空间复杂度和O(n)时间复杂度:3.除遍历a[N] b[N]使用的计数器外,不使用任何新的变量(包括栈临时变量.对空间和全局静态变量等): /**********************************************/ /* 给定一个数组a[N],我们希望构造数组b[N],其中b[i]=a[0]*a[1]*...*a[

【笔试题-腾讯】给定一个数组a[N],我们希望构造数组b[N]

腾讯2012实习生笔试题(加分题): 给定一个数组a[N],我们希望构造数组b[N],其中b[i]=a[0]*a[1]*...*a[N-1]/a[i].在构造过程: a)不允许使用除法: b)要求O(1)空间复杂度和O(n)时间复杂度: c)除遍历计数器与a[N] b[N]外,不可使用新的变量(包括栈临时变量.对空间和全局静态变量等): 请用程序实现并简单描述. 题意应该不难理解,乍一看有点儿无从下手的感觉,思考后没有突破的话就想放弃了.看到网上其他同学也给出了解法,代码很简洁,但是理解起来不是

程序员代码面试指南 IT名企算法与数据结构题目最优解 ,左程云著pdf高清版免费下载

下载地址:网盘下载 备用地址:网盘下载 内容简介  · · · · · ·这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮助广大程序员的面试准备做到万无一失.“刷”完本书后,你就是“题王”!__eol__本书采用题目+解答的方式组织内容,并把面试题类型相近或者解法相近的题目尽量放在一起,读者在学习本书时很容易看出面试题解法之间的联系,使知识的学习避免碎片化

算法总结——堆栈

先说stack的题目 stack的实现:链表,数组 题目: (1)简单的:min stack,一个数组实现三个stack (2)经典的stack问题:经典汉诺塔问题,逆波兰式计算或者产生逆波兰式,简化文件路径,验证括号对是否合法,找出最长有效括号(贪心+stack求解) (3)涉及tree的遍历问题:tree中序遍历的迭代解法,二叉搜索树的两节点和(two sum思路) (4)***stack排序问题***:为stack排序,从柱状图里找最大矩形(本质上类似stack排序),构造数组的maxtr