首页 > 其他分享 >攒青豆 | 「青训营 X 码上掘金」主题创作

攒青豆 | 「青训营 X 码上掘金」主题创作

时间:2023-01-31 14:44:42浏览次数:55  
标签:柱子 遍历 int 码上 高度 height 青豆 青训营

当青训营遇上码上掘金

题目介绍

攒青豆

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

攒青豆.png

以下为上图例子的解析:

输入:height = [5,0,2,1,4,0,1,0,3]  
输出:17  
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。

题目分析

这题需要用到简单的动态规划。先对数组中的所有元素进行一次预处理:从右往左遍历找到每一根柱子右侧最高的柱子,再从左往右遍历找到每一根柱子左侧最高的柱子。对于每一柱子,能攒青豆的量就是左右两侧最高柱子的最小值与当前柱子的高度的差值,最后,将所有能接住的青豆数量相加。

这题原题就在leetcode上,只是换了个背景,我很早之前还提交过42. 接雨水。由于对码上掘金并不熟悉也不会使用(他调试还要自己写在html的吗?根本不知道写哪,不过我代码是可以跑的),我在c++窗口写上了类ACM模式的代码并且合并了我leetcode的代码,没有做更多的创作。

思路模拟

求每一列能攒的青豆数,我们只需要关注当前列,左边最高的墙,右边最高的墙就够了。

青豆的数量,根据短板效应,我们只需要看当前柱子左边最高的柱子和右边最高的柱子中较矮的一个的高度。

所以,根据较矮的那个柱子和当前列的柱子的高度可以分为三种情况。

  • 较矮的墙的高度大于当前列的墙的高度

    很明显,较矮的一边,也就是左边的柱子的高度,减去当前列的高度就可以了。

  • 较矮的墙的高度小于当前列的墙的高度

    正在求的列不会有青豆,因为它大于了两边较矮的墙。

  • 较矮的墙的高度等于当前列的墙的高度。

    和上一种情况是一样的,不会有青豆留下。

明白了这三种情况,程序就很好写了,遍历每一列,然后分别求出这一列两边最高的墙maxl和maxr。找出较矮的一端,和当前列的高度比较,结果就是上边的三种情况。

这样遍历每一列左边最高的柱子和右边最高的柱子的时间复杂度是O(n^2)​。

但是

我们注意到对于每一列,我们求它左边最高的柱子和右边最高的柱子(不包括自己),都是重新遍历一遍所有高度,这里可以优化。

首先利用两个数组,l[i]表示第i列柱子左边最高的柱子的高度,r[i]​代表第​i​列柱子右边最高的柱子的高度。

对于l[i]可以遍历height,l[i] = max(l[i - 1], height[i - 1])得到,同理r[i]​可由r[i] = max(r[i + 1], height[i])得到,注意边界条件。这样,对于直接模拟无需每次重新遍历一次求maxl和maxr了。

最后对于每一列res += max(0, min(l[i], r[i]) - height[i - 1]),当前列表示左右两边最搞的柱子中更低的一个,减去当前列柱子的高度即是当前列可以攒的青豆数。

时间复杂度:O(n)​。空间复杂度:O(n)​。

显然更优。

代码

#include<bits/stdc++.h>
using namespace std;
class Solution {
	public:
		int l[20002], r[20002];
		int trap(vector<int>& height) {
			l[0] = 0;
			r[height.size()] = 0;
			for (int i = 0; i < (int)height.size(); i ++) l[i + 1] = max(l[i], height[i]);
			for (int i = height.size() - 1; i >= 0; i --) r[i] = max(r[i + 1], height[i]);
			int res = 0;
			for (int i = 1; i <= (int)height.size(); i ++) res += max(0, min(l[i], r[i]) - height[i - 1]);
			return res;
		}
};
void solve() { //为什么没有调试,不会用,手写个调试的东西 
	int n;
	vector<int> v;
	Solution sol;
	cin >> n; //柱子个数
	for(int i = 1, x;i <= n;i ++) {
		cin >> x;
		v.push_back(x); //输入柱子高度 
	} 
	cout << sol.trap(v) << endl;
	return;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	solve();
	return 0;
}
/*
sample input:
9
5 0 2 1 4 0 1 0 3
sample output:
17
*/

后言

青训营的活动规则实在是太多,想要结营,在无法获得四等奖及以上的情况下必须所有的活动都全部全勤,而运营并没有很清楚的说明规则,或者是说明的太乱,导致很多人或多或少的没做完,比如我的阅读打卡我今天才发现还缺了一个限制,还无法修改我的阅读打卡内容。目前的18天里面有没有1天都是个问题。我知道这些规则很有利于掘金社区的内容创作,但是并没有讲清楚缺了xx就会无法计数什么的,也没有挽回的办法。希望运营能写的更清楚些吧,最好搞整合的文档而不是东一个西一个,少点限制和要求,总是害怕又漏了什么规则没看,导致多天的学习创作攒不了青豆,这些规则并没有利于技术的学习,还会影响学员的结营证书和参营积极性,属实是失望......

标签:柱子,遍历,int,码上,高度,height,青豆,青训营
From: https://www.cnblogs.com/peace0218/p/17078898.html

相关文章

  • 14--git常用操作 | 青训营笔记
    这是我参与「第五届青训营」伴学笔记创作活动的第14天学习资料git使用简易指南(bootcss.com)Git-Book(git-scm.com)公司使用Gitlab管理项目实践指南git思维导......
  • 13--linux常用操作 | 青训营笔记
    这是我参与「第五届青训营」伴学笔记创作活动的第13天Linux命令大全|菜鸟教程(runoob.com)1.ls命令ls可能是每个Linux用户在其终端中键入的第一个命令。它允许......
  • 02pycharm 如何添加代码上传到gitlab
    1.首先正确安装好python,pycharm工具(这边不做介绍) 2.下载git的windows客户端官网:https://git-scm.com/download/win  根据自己的系统选择合适的版本,下载安装......
  • 12--go mod和go vendor的区别 | 青训营笔记
    这是我参与「第五届青训营」伴学笔记创作活动的第12天背景在家安装的环境可能路径和环境变量配的有些问题,导致项目import的包全部标红,gomodtidy显示导入包不在路径,......
  • 11--go mod遇到的小问题 | 青训营笔记
    这是我参与「第五届青训营」伴学笔记创作活动的第11天gopath不起作用 cannotfindmoduleprovidingpackagegithub.com原因:使用代理下载go包后后,出现了找不到包......
  • 10--限流技术学习 | 青训营笔记
    这是我参与「第五届青训营」伴学笔记创作活动的第10天简介所谓限流,就是指限制流量请求的频次。它主要是在高并发情况下,用于保护系统的一种策略,主要是避免在流量高峰导......
  • 9--Websoket学习 | 青训营笔记
    这是我参与「第五届青训营」伴学笔记创作活动的第9天简介WebSocket是基于TCP/IP协议,独立于HTTP协议的通信协议。双向通讯,有状态,客户端一(多)个与服务端一(多)双向实时响......
  • [ 7--MQ学习 | 青训营笔记]
    这是我参与「第五届青训营」伴学笔记创作活动的第7天概述消息队列(MessageQueue,简称MQ),指保存消息的一个容器,本质是个队列。消息(Message)是指在应用之间传送的数据,消息......
  • [ 6--JWT学习 | 青训营笔记]
    这是我参与「第五届青训营」伴学笔记创作活动的第6天JWT介绍JSONWebToken(orJWT)只是一个包含某种意义数据的JSON串。它最重要的特性就是,为了确认它是否有效,我们......
  • [ 5--Token学习 | 青训营笔记]
    这是我参与「第五届青训营」伴学笔记创作活动的第5天Token介绍Token,就是服务端生成的一串加密字符串、以作客户端进行请求的一个“令牌”。当用户第一次使用账号密码......