下午,羣裏面有同窗出了一個簡單的算法題,意思是一個房間內,有多個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; }