下午,群里面有同窗出了一个简单的算法题,意思是一个房间内,有多个1立方米的箱子,多个箱子能够垂直落在一块儿,问:剩下的空间能够存多少立方的水(如图)。算法
本身算法一直很差,可是用进废退,脑子仍是得多适应如下这种算法的问题。数组
简单来讲,你们作惯了各自字符串,数组,链表的题,出题者但愿经过一个变种的方式影响如下作题者的思路。 简单梳理了一下,其实这个题能够是个数组题,就是将横坐标做为索引,纵坐标箱子的高度做为数组值,因而能够简单的变为:[0,1,0,4,1,0,1,3 ...]code
根据木桶理论能够知道,影响盛水多少是由最短的一看板子决定的,因而思路是,求得指定索引区间内,数组中的第一高度和第二高度,这两个index的步长做为宽,第二高度做为高,再减去区间内的全部箱子获得最终的值:递归
宽 * 高 - 占有的箱子索引
private static int sum = 0; private static List list = new ArrayList(); list.add(0); list.add(1); list.add(0); list.add(4); list.add(1); list.add(0); list.add(1); list.add(3); list.add(0); list.add(6); list.add(0); list.add(1); list.add(0); list.add(3); getSum(0, list.size() - 1); System.out.println("sum:" + sum);
经过递归方式,获得给定区间内的对高值和第二高值,并求出中间面积图片
private static void getSum(int start, int end) { // 获取第一高点和第二高点 int firstIndex = 0; int firstH = 0; int secondIndex = 0; int secondH = 0; int h = 0; for (int i = start; i <= end; i++) { h = Integer.parseInt(list.get(i).toString()); if (h > firstH) { firstH = h; firstIndex = i; } } for (int i = start; i <= end; i++) { if (i == firstIndex) continue; h = Integer.parseInt(list.get(i).toString()); if (h > secondH) { secondH = h; secondIndex = i; } } int left = firstIndex >= secondIndex ? secondIndex : firstIndex; int right = secondIndex >= firstIndex ? secondIndex : firstIndex; if (right - left == 1) return; // 获取所有面积 h = firstH > secondH ? secondH : firstH; int skip = right - left - 1; int count = skip * h; // 删除掉占用的块 int remove = removeBlock(left + 1, right); sum += count; sum -= remove; if (left - start > 1) getSum(start, left + 1); if (end - right > 1) getSum(right - 1, end); }
删除区间内的实体箱子ip
private static int removeBlock(int start, int end) { int remove = 0; for (int i = start; i < end; i++) { remove += Integer.parseInt(list.get(i).toString()); } return remove; }