当前位置: 首页 > news >正文

codility上的问题 (21) Upsilon 2012

这是我目前最喜欢的codiltiy上的问题之一。问题描述是:给定一个整数数组A,所有的数均不相同。假设下标从0开始,找到一个数组B, 满足A[B[0]] > A[B[1]] > A[B[2]] >...A[B[K]],对任意两项A[B[i]]和A[B[i + 1]],任意j,  min(B[i],B[i + 1]) < j < max(B[i],B[i + 1]) 均有A[j] < A[B[i + 1]] ,求最大的K。

例如,对数组 A,

 

A[0]  =  9   A[1]  = 10   A[2]  =  2
A[3]  = -1   A[4]  =  3   A[5]  = -5
A[6]  =  0   A[7]  = -3   A[8]  =  1
A[9]  = 12   A[10] =  5   A[11] =  8
A[12] = -2   A[13] =  6   A[14] =  4

 

 

求得的数组B为 9,1,4,8,6,7,长度为6

 

 A[9] = 12    A[1] = 10    A[4] =  3
 A[8] =  1    A[6] =  0    A[7] = -3

 

 

输入数组A的长度n [1..10^5],数组元素范围[-10^9,+10^9],都是整数且不相同。

要求复杂度 时间空间都是O(n)。


分析: 这个题乍一看没思路。需要转换:我们把A中得数建成一个类似”堆“的结构。对A数组,这个二叉树的根是最大值,然后我们把最大值两边的部分分别建立成这样的二叉树(每段递归的找最大值)。我们暂时抛开建树的复杂度,如果有了这样的树,我们所以的B数组长度对应为从树根到叶子的叶子的一条路径长度。(因为每个子树的根都是最大值)。那么如何建立这样的树呢? 暴力递归的方法会导致O(n^2)的复杂度。如果我们从做到右扫描A数组,假设某个值是当前最大值,它的左子树所有的元素都确定了,再出现的数,要么放在它的右子树,要么它成为别人的左子树。对于任意一个元素来讲,要么它成为之前元素的右子树,要么之前某个元素成为它的左子树,这取决于大小关系。我们在算一个元素的右子树的时候,因为元素还没扫描完,所以我们很难确定什么时候把它作为某个元素的右子树位置。 我们可以保存这样一个栈,栈的每个元素是一棵树,树根的左子树已经完全确定,根的右子树暂时是空。当弹出一棵树的时候,我们需要把它下面那个元素的子树合并。

也就是说,栈考顶得元素是其下面元素的右子树,但是右子树会变化。

大概过程如下:

如果当前元素比栈顶元素大,就把栈顶元素弹出,新弹出的元素作为之前弹出元素的右子树,都弹出之后形成的树,作为当前元素的左子树(右子树为空),形成的树放入栈。因为弹出来的东西都比当前元素小,并且在当前元素的左边。另外,我们不会真得合并树,只记录树的高度即可(根到叶子的节点个数)。代码非常简单:


 

// you can also use includes, for example:
// #include <algorithm>
int solution(const vector<int> &A) {
    // write your code here...
    int i, height, n = A.size();
    vector<pair<int,int> > s;
    for (i = 0; i < n; ++i) {
        for (height = 0; (!s.empty()) && (s.back().first < A[i]);s.pop_back()) {
            height = max(height + 1, s.back().second);
        }
        s.push_back(make_pair(A[i], height + 1));
    }
    for (height = 0; !s.empty();s.pop_back()) {
        height = max(height + 1, s.back().second);
    }
    return height;
}


 

 

 

相关文章:

  • Go语言语法汇总
  • instanceof关键字
  • [LeetCode] Max Points on a Line
  • Appium 三种wait方法(appium 学习之改造轮子)
  • 文件服务器 之 Debian下配置使用Subversion版本控制服务器
  • 浏览器缓存机制(转)
  • C#网络编程系列文章索引
  • iOS Web应用开发:运用HTML5、CSS3与JavaScript
  • Makefile 中:= ?= += =的区别
  • centos7zabbix-agen安装
  • vue-i18n beforeDestroy不能调用this.$t
  • 验证码识别并复制到剪切板
  • cheerp 简介
  • CSS 三角实现
  • 第十二章 Java内存模型与线程
  • 【剑指offer】让抽象问题具体化
  • ES6 学习笔记(一)let,const和解构赋值
  • git 常用命令
  • java正则表式的使用
  • Rancher如何对接Ceph-RBD块存储
  • windows-nginx-https-本地配置
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 记录一下第一次使用npm
  • 开发基于以太坊智能合约的DApp
  • 判断客户端类型,Android,iOS,PC
  • 深度学习中的信息论知识详解
  • 探索 JS 中的模块化
  • 小程序01:wepy框架整合iview webapp UI
  • 一、python与pycharm的安装
  • ​【已解决】npm install​卡主不动的情况
  • ​Python 3 新特性:类型注解
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • (1)(1.13) SiK无线电高级配置(五)
  • (1)SpringCloud 整合Python
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (3)nginx 配置(nginx.conf)
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (二)linux使用docker容器运行mysql
  • (分布式缓存)Redis分片集群
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET gRPC 和RESTful简单对比
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout
  • .net对接阿里云CSB服务
  • .NET连接数据库方式
  • .NET命令行(CLI)常用命令
  • .Net语言中的StringBuilder:入门到精通
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • // an array of int
  • [ACTF2020 新生赛]Include
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • [AX]AX2012开发新特性-禁止表或者表字段
  • [bzoj4240] 有趣的家庭菜园