攒青豆之接雨水|青训营笔记

97 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 31 天

前世今生

之前在青训营开始的时候给了一个攒青豆的题目,当时给的例子较简单,可以想到的情况也比较少,所以简单编码后,通过了测试用例就草草提交了,前几天在力扣又刷到了这个题,不过名字改成了接雨水,我本想直接套过来的,但发现第一个例子就不可行。所以就又有了这一篇。

看这篇之前建议看看我原来的

我原来的文章

当青训营遇上码上掘金 - 掘金 (juejin.cn)

最终版更新了,这个是可行解,小伙伴们移步

接雨水最终版 - 掘金 (juejin.cn)

错误发现

首先第一个例子就打破了我原来的思路

image.png

我原来的思路就是直接将最大高度两侧分成两个池子直接计算

int results = (m_size-h_size-1)*(max<header?max:header)+(t_size-m_size-1)*(max<tail?max:tail);

那个例子刚好可以用,但这个不可以,因为在左边界与中间最大高度之间有一个高度大于边界值的所以不可以,原来的例子中刚好边界值都大于中间的max。

下一步思路

我又顺着这个思路想,那不就是中间的max小于两侧边界值就可以了吗。显然是可行方案。那就继续划分呗,将左侧的池子划分成两个池子,边界就是原池子左边界+max,另一个是max+原右边界。那现在划分开了怎么找新池子中雨水呢?显然,我们这个程序就是处理这个问题的,再将新池子传回次函数,也就是递归了。 当max小于等于两边界时,执行之前的计算逻辑。

if(max<=header&&max<=tail){
results = (t_size-h_size-1)*(header<tail?header:tail);
//忽略其他元素得到的初步结果
for (int i =h_size+1;i<t_size;i++){//减去其他元素
 results = results -height[i];
 }
return results;
}
results = trap(Arrays.copyOfRange(height, h_size, m_size+1)) + trap(Arrays.copyOfRange(height, m_size, t_size+1));

这段代码对原来的代码进行的改动,原来的计算分成了两部分,其实直接计算整体就可以。

这里有一个细节 Arrays.copyOfRange(height, h_size, m_size+1) 此函数作用是对一个已有的数组进行截取复制,复制出一个左闭右开区间 的数组。这个耽误我挺长时间的,大家注意一下,我后来还是把代码拷到本地调试才发现的(平台不能调试,当时就乱改一通)。这类问题我还犯了不止一次,之前刷题的时候有个求商问题,要求考虑int型数据的边界值,它的区间也是左闭右开的,当时就把两侧都当成闭区间耽误了很长时间,所以大家一定要注意边界问题。

然后就是递归结束条件了,只要是传进来的数组长度小于3就是接不到雨水的,因为想接到雨水必须有边界,还应该有一个位置来存储雨水,所以长度至少为3。还有就是当左边界与右边界在同一位置时是不可以的,例如{1,2,1}图示(不会画图,将就看)

image.png

这样显然是接不到的。

if(height.length<3) return 0;//这一条在找边界前,否则会产生数组元素溢出的情况
if(h_size == t_size) return 0;//这一条在找边界后

但这个方法在力扣最后也没通过,内存超出限制了,给了一个从1到14999的数组,两个屏幕都放不下......每次传入数组都会分配6个变量,这个都传多少次了,肯定内存分配不够

虽然没通过,但这个方法是可行的

原来的代码有些问题,现在以新的为准确

完整代码贴到掘金了,感兴趣的小伙伴可以看看

完整代码

最后

这个题虽然之前思路就很清晰了,但再刷到后还是做了好几天,能力不足吧,继续努力了,那种解决问题的感觉真的让人上头。诸君共勉。有不足的地方可以评论给我。