前言
这道面试题是我在博客园首页的一篇文章中看到的,面试题我简单的提取出来了,文章链接:http://news.cnblogs.com/n/192014/。
在我用JS实现了我自己的想法之后,我再一次看了这篇文章。在这篇文章的评论里,我惊喜的发现,有些大牛给出了更好的思路,
我会备注在这篇文章的后面,也可以直接去看原文的评论。博客园大牛还是很多的,程序猿是很聪明的群体。:):)
面试题
一个平面上有很多墙,高度参差不齐,每堵墙平行挨着,如下图所示,
计算如下所示的图墙可装水量,框里面的数字代表墙的高度
具体实现
1.可以先试着思考下怎么做:)
2.用JS实现的

1 /** 2 * 思路: 3 * 1.确定可装水的区域 4 * 区域满足如下条件才可装水: 5 * a. 必须包含至少三堵墙 6 * b. 最左(右)侧的墙的高度必须小于另外一侧 7 * c. 非最外侧的墙的高度一定小于或者等于最外侧墙中最小的高度的墙 8 * 2.计算可装水区域内某堵墙可装水的容积volume 9 * 3.计算可装水区域内所有墙可装水容积之和 10 * 4.计算所有可装水区域容积之和 11 * 12 * 实现: 13 * 1 找出最高墙的位置 iMaxIdx 14 * 2 从左至右计算可装水容积 V1 直至第iMaxIdx堵墙 15 * 3 从右至左计算可装水容积 V2 直至第iMaxIdx堵墙 16 * 4 总的可装水容积:V1+V2 17 */ 18 var aWallH = [2,5,1,2,3,4,7,7,6]; //所有墙的高度 19 var iWallW = 1; //墙宽度 20 var iWallL = 1; //墙长度 21 var iTotalV = 0; //总可装水容积 22 var iMaxWallIdx = 0; //最高墙的位置 23 var getMaxIdx = function(aO){ //找出最高墙的位置 24 var iMax = 0,iIdx = 0; 25 for (var i = 0; i < aO.length; i++){ 26 if (iMax < aO[i]){ 27 iMax = aO[i]; 28 iIdx = i; 29 } 30 } 31 return iIdx; 32 }; 33 var calVolume = function(aO,start,end,x,w,l){ //计算可装水容积 34 var iLeftH = 0; 35 var iAreaV = 0; 36 var iTotalV = 0; 37 var i = start; 38 for (; (x == 1) ? (i <= end) : (i >= end); i = i + x){ 39 if (iLeftH < aO[i]){ 40 iLeftH = aO[i]; 41 } else { 42 break; 43 } 44 } 45 for (; (x == 1) ? (i <= end) : (i >= end); i = i + x){ 46 if (iLeftH > aO[i]){ 47 iAreaV += (iLeftH - aO[i]) * w * l; 48 } else { 49 iLeftH = aO[i]; 50 iTotalV += iAreaV; 51 iAreaV = 0; 52 } 53 } 54 return iTotalV; 55 } 56 iMaxWallIdx = getMaxIdx(aWallH); 57 iTotalV += calVolume(aWallH,0,iMaxWallIdx,1,iWallW,iWallL); 58 iTotalV += calVolume(aWallH,aWallH.length-1,iMaxWallIdx,-1,iWallW,iWallL); 59 console.log(iTotalV);
博客园大牛给出的更好的思路
还是折叠吧:):)

1 /* 2 * 第7楼osold发表于 2013-11-01 14:06 3 * 这个其实对应图形学里面的一个扫描线填充算法。 4 *用那个算法实现比较简单。 5 */ 6 7 /* 8 * 备注:此方法有问题! 第12楼Kalou发表于 2013-11-01 17:12 9 *将n个点按顺序连接成折线,分别计算每2个点之间的高度差, 10 *当遇到第一个负数时,表示可能开始收集到水,与后面的数相加, 11 *知道大于0,此区间*代表能收集到水。依次类推。例如 12 *10块砖的高度分别为[2,5,1,3,1,2,1,7,7,6], 13 *此时他们之间的距离分别为 [+3,-4,+2,-2,+1,-1,+6,+0,-1], 14 *第一个负数为-4,代表5这里可能开始**收集到水, 15 *然后向下遍历,-4+2《=0,-4+2-2《=0,-4+2-*2+1《=0,-4+2-2+1-1《=0,-4+2-2+1-1+6》0, 16 *这里终止,代表*收集雨水区域为[5,1,3,1,3,1,7] 17 */
后记
1. js功能很强并执行方便,所以我选择了JS实现。
2.思路都是相同的,用其他语言一样可以实现,这个看个人的喜好。
3.实现思路就可以称之为算法吧,不只局限排序 :)
4.有空多思考,多训练,否则长久下去,思维会变迟钝。