当青训营遇上码上掘金
主题4的题目为:
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
解答思路分享
刷过算法题目的朋友都应该比较熟悉,这道题类似于力扣上的接雨水问题(双指针) 这里我用自己的理解进行解答:
①首先前端代码:
只需要增加一个输入框,一个按钮,按钮响应后将custom端的结果返回到输出框中。
a. 需要在HTML代码中添加一个输入框元素,并为其添加一个id,
b. 添加一个按钮元素,并为其添加一个事件监听器,在监听器中读取输入框中的值,并将其传递给custom端
c. 添加一个输出框元素,并为其添加一个id。然后在JavaScript代码中读取custom端的输出,并将其写入输出框
代码较为简单,如下:
<div id="app"></div>
<div>
<input type="text" id="input-array">
<button id="submit-btn">提交</button>
</div>
<div>
<textarea id="output-result"></textarea>
</div>
<script type="module">
import {CodeXClient, logger} from 'https://cdn.jsdelivr.net/npm/jcode-tools@^0.10.2/dist/jcode-tools.esm.js';
(async () => {
window.console = logger(app);
console.log('题目: 现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)');
console.log('请输入一个数组表示各个柱子高度(空格分隔),按确定后得出结果(耐心等待)');
const inputArray = document.getElementById('input-array');
const outputResult = document.getElementById('output-result');
const submitBtn = document.getElementById('submit-btn');
try {
const code = new CodeXClient(); // 默认会从CustomCode中获取
submitBtn.addEventListener('click', async () => {
/*console.log('提交数组:', inputArray.value);-->*/
const result = await code.runCode({input: inputArray.value});
if(result?.error) {
console.error(result.error);
}
/*console.log(result.output);*/
outputResult.value = result.output;
});
} catch(ex) {
console.error(ex);
}
})();
</script>
②custom端
直接用c++进行解答即可。
思路: 最高的两个柱子(左边位置l,右边位置r)之间肯定可以装青豆,只需要遍历两根柱子区间就可以得出青豆数。依次找到在左边(或右边)第三高的柱子,这个柱子和原来的左边柱子(右边柱子)之间也可以装青豆,依此类推。
柱子高度记录在vector<int> A中,柱子的高度及其位置记录在vector<st> M中
①将M根据柱子的高度进行排序。
最高的两个柱子(左边位置l,右边位置r)之间肯定可以装青豆,只需要遍历两根柱子区间就可以得出青豆数。
②从大到小按顺序遍历M: 初始化l=r=最高的柱子位置
a.如果柱子的位置t < l , 那么t到l之间可以装青豆数,遍历一下A数组的[t,l]区间即可
b.如果柱子的位置t > r , 那么t到l之间可以装青豆数,遍历一下A数组的[r,t]区间即可
c.其余情况不做处理
时间复杂度分析:O(nlog(n))
主要有三部分:排序 : O(nlogn) 遍历M : O(n) 遍历区间实际上只遍历了一遍A数组: O(n)
代码:
#!/jcode/lang/cpp https://xitu.github.io/jcode-languages/dist/lang-cpp.json
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int min(int a, int b)
{
return a < b ? a : b;
}
struct st
{
int height;
int index;
st() {};
st(int h, int i) { height = h; index = i; }
bool operator<(const st b)
{
return height < b.height;
}
};
int main() {
vector<int> A;
vector<st> M;
int t; int index = 0;
while (cin >> t) {
A.push_back(t);
M.push_back(st(t, index));
index++;
if (index == 9) break;
}
if (A.size() == 1) cout << "可以装的青豆数量为:" << 0 << "(个单位)" << endl;
int l, r;
int res = 0;
sort(M.begin(), M.end());
for (int i=M.size()-1;i>=0;i--)
{
if (i==M.size()-1) {
l = r = M[i].index; continue;
}
if(M[i].index>r)
{
int t = M[i].index;
int m = min(A[r], A[t]);
for (int i = r + 1; i < t; i++) { res += m - A[i]; }
r = t;
}
if (M[i].index < l)
{
int t = M[i].index;
int m = min(A[t], A[l]);
for (int i = t+1; i < l; i++) { res += m - A[i]; }
l = t;
}
};
cout << "可以装的青豆数为:" << res << "(个单位)" << endl;
return 0;
}