一道Twitter面试题的解答

前言

这道面试题是我在博客园首页的一篇文章中看到的,面试题我简单的提取出来了,文章链接:http://news.cnblogs.com/n/192014/

在我用JS实现了我自己的想法之后,我再一次看了这篇文章。在这篇文章的评论里,我惊喜的发现,有些大牛给出了更好的思路,

我会备注在这篇文章的后面,也可以直接去看原文的评论。博客园大牛还是很多的,程序猿是很聪明的群体。:):)

面试题

一个平面上有很多墙,高度参差不齐,每堵墙平行挨着,如下图所示,
计算如下所示的图墙可装水量,框里面的数字代表墙的高度

twitter面试题

具体实现

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);
View Code

博客园大牛给出的更好的思路

还是折叠吧:):)

 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  */
View Code

后记

1. js功能很强并执行方便,所以我选择了JS实现。

2.思路都是相同的,用其他语言一样可以实现,这个看个人的喜好。

3.实现思路就可以称之为算法吧,不只局限排序 :)

4.有空多思考,多训练,否则长久下去,思维会变迟钝。

作者:WadeYu
出处:http://www.cnblogs.com/wadeyu/
本文版权归本人和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/wadeyu/p/3404578.html