当青训营遇上码上掘金
背景
攒青豆这道题是典型的“接雨水”这道题的转型题,青训营的运营团队把雨水换成青豆真是太有想象力了,完美诠释了每位青训营同学寒假的生活状态,哈哈哈哈(希望我“攒青豆”的输入为[7,0,0,0,0,0,0,0,0,0,0,7](手动狗头))。
思路解析
首先说一下看到这道题的两个切入面,一个是横向即先从下往上,再从左往右挨个判断每个位置是否可以放下青豆,一个是纵向即从左到右遍历数组,判断每列可以攒下的青豆数量。
横向的算法其实是一种暴力解法,先设结果int res = 0。由于左右2侧不可能攒下青豆,所以每次计算从第二列开始,倒数第二例结束。从下到上每行遍历,以第n行为例,从左到右遍历每一行的柱子。如果这列柱子的高度小于n,并且这列的左右都有大于等于n的柱子,res++。最后直到最高柱子一行截止,得到的res即为最终的结果,时间复杂度O(m*n)。
纵向的算法在一定程度上做了很大的优化,只从左到右遍历一次数组,计算得到每列柱子左右各自的最大高度,取二者中的最小值,若该值大于此列柱子高度,取二者差加入结果。
在纵向的算法上还可以做一定程度的优化,利用双指针的思想,我们都知道水桶的短板问题,控制水桶水量的是最短的一条板子。这道题也是类似,我们可以将整个图看成一个水桶,两边就是水桶的板,中间比较低的部分就是水桶的底,由较短的边控制水桶的最高水量。但是水桶中可能出现更高的边,比如上图第四列,它比水桶边还要高,那这种情况下它是不是将一个水桶分割成了两个水桶,而中间的那条边就是两个水桶的边。
最终我们得到的算法的编程结果如下所示:
import java.util.*;
public class Solution {
public long maxWater (int[] arr) {
//排除空数组
if (arr.length == 0)
return 0;
long res = 0;
//左右双指针
int left = 0;
int right = arr.length - 1;
//中间区域的边界高度
int maxL = 0;
int maxR = 0;
//直到左右指针相遇
while (left < right){
//每次维护往中间的最大边界
maxL = Math.max(maxL, arr[left]);
maxR = Math.max(maxR, arr[right]);
//较短的边界确定该格子的水量
if(maxR > maxL)
res += maxL - arr[left++];
else
res += maxR - arr[right--];
}
return res;
}
}
问题
给出的结果是leetcode模式下的算法过程,而对于acm模式还要考虑其输入输出,我在我的码上掘金上给出了如下的代码,在本地IDEA上可以顺利运行,但是码上掘金平台一直下图所示报错,希望日后能够找到原因吧。
/** * 支持 import Java 标准库 (JDK 1.8) */import java.util.*;/** * 注意:目前 Java 代码的入口类名称必须为 Main(大小写敏感) */public class Main { private static Scanner sc = new Scanner(System.in); public static void main(String []args) { //处理输入部分,得到对应的数组 //Scanner sc = new Scanner(System.in); String str1 = sc.next(); str1 = str1 + sc.next(); str1 = str1 + sc.next(); sc.close(); int n = str1.length(); String str = str1.substring(8, n - 1); String[] arr = str.split(","); int[] heights = new int[arr.length]; for (int i = 0; i < heights.length; i++) { heights[i] = Integer.parseInt(arr[i]); } //处理过程 int res = 0, len = heights.length; int i = 0, j = len - 1; int maxL = heights[0], maxR = heights[j]; while (i < j) { maxL = Math.max(maxL, heights[i]); maxR = Math.max(maxR, heights[j]); if (maxL < maxR) { res += (maxL - heights[i]); i++; } else { res += (maxR - heights[j]); j--; } } //sc.close(); System.out.println(res); }}