左神算法书籍《程序员代码面试指南》——1_08构造数组的MaxTree

【题目】

将一个没有重复数字的数组中的数据构造一个二叉树
每个节点都是该子树的最大值
【要求】
时间复杂度为O(N)
【题解】
使用单调栈,栈的顺序是维持从大到小排序
通过使用单调栈,将数组中中所有数的左右比他大的数记录下来
当某个数既无左边比他大的数,有无右边比他大的数,则该数为全局最大,将其作为二叉树的根
然后,某数只有左比他大的数,或者右比他大的数,则该数直接挂在比他大的数的下面,
当某个数既有左比他大的数,又有右比他大的数,则挂在两个数中较小数的下面。
然后直接构成一棵树。

 

  1 #include <iostream>
  2 #include <vector>
  3 #include <deque>
  4 #include <sstream>
  5 
  6 using namespace std;
  7 
  8 struct Node
  9 {
 10     int val;
 11     Node* lchild;
 12     Node* rchild;
 13     Node(int a) :val(a), lchild(nullptr), rchild(nullptr) {}
 14 };
 15 
 16 void creatMaxTree(Node*& root, vector<int>v)
 17 {//以下代码都是以数组的下角标为根据
 18     vector<Node*>node;
 19     vector<pair<int, int>>res;//存储每个数的左右大小的数
 20     res.resize(v.size());
 21     deque<int>d;//单调栈
 22     for (int i = 0; i < v.size(); ++i)
 23     {
 24         Node* p = new Node(v[i]);
 25         node.push_back(p);//先生成相关的节点
 26         while (!d.empty() && v[i] > v[d.back()])
 27         {
 28             int index = d.back();
 29             d.pop_back();
 30             if (d.empty())//有右大值,无左大值
 31                 res[index] = pair<int, int>(-1, i);
 32             else//有右大值和左大值
 33                 res[index] = pair<int, int>(d.back(), i);
 34         }
 35         d.push_back(i);
 36     }
 37     while (!d.empty())
 38     {
 39         int index = d.back();
 40         d.pop_back();
 41         if (d.empty())//即无右大值,又无左大值
 42             res[index] = pair<int, int>(-1, -1);
 43         else//无右大值有左大值
 44             res[index] = pair<int, int>(d.back(), -1);
 45     }
 46     for (int i = 0; i < res.size(); ++i)
 47     {
 48         int a, b;
 49         a = res[i].first;
 50         b = res[i].second;
 51         if (a == -1 && b == -1)//即无右大值,又无左大值为根节点
 52             root = node[i];
 53         else if (a == -1 && b != -1)
 54             node[b]->rchild = node[i];
 55         else if (a != -1 && b == -1)
 56             node[a]->lchild = node[i];
 57         else if (v[a] > v[b])
 58             node[b]->rchild = node[i];
 59         else
 60             node[a]->lchild = node[i];
 61     }
 62 }
 63 
 64 //打印树形状进行查看
 65 class PrintTree
 66 {
 67 public:
 68     void Print(Node* root)
 69     {
 70         cout << "The shape of tree is: " << endl;
 71         cout << "=============================================================" << endl;
 72         PrintShape(root, 0, "H", 17);
 73         cout << "=============================================================" << endl;
 74     }
 75     void PrintShape(Node* root, int h, string c, int len)
 76     {
 77         if (root)
 78         {
 79             PrintShape(root->rchild, h + 1, "v", len);
 80             string val;
 81             stringstream ss;
 82             ss << root->val;
 83             ss >> val;
 84             val = c + val + c;
 85             int lenM = val.length();
 86             int lenL = (len - lenM) / 2;
 87             int lenR = len - lenM - lenL;
 88             val = getSpace(lenL) + val + getSpace(lenR);
 89             cout << getSpace(h*len) + val << endl;
 90             PrintShape(root->lchild, h + 1, "^", len);
 91         }
 92 
 93     }
 94     string getSpace(int num)
 95     {
 96         string space = " ";
 97         for (int i = 0; i < num; ++i)
 98             space.append(" ");
 99         return space;
100     }
101 };
102 
103 void Test()
104 {
105     vector<int>v;
106     v = { 5,3,4,2,6,1 };
107     Node* root = nullptr;
108     creatMaxTree(root, v);
109     PrintTree print;
110     print.Print(root);
111 }

 

转载于:https://www.cnblogs.com/zzw1024/p/11180611.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值