题目:高低不平的台阶,问下雨时能够储存多少水。
分析:
(1)存水区域的边界必然是曲线由增变减的拐点,因此需要找出所有拐点。
(2)如果一个拐点的高度值小于左右两个拐点的高度值,那么该点被淹没在左右两拐点的水面下,应当舍弃此点。
程序:
1 def step_water(steps): 2 """ 求出台阶能够存储的水量。 3 4 Args: 5 steps: 各台阶的高度。 6 7 Returns: 8 存储的水量 9 """ 10 i = 0 11 increasing = True 12 inflection_point = [] 13 water = 0 14 15 # 找出台阶的所有拐点 16 while i < len(steps) - 1: 17 if steps[i] >= steps[i + 1] and increasing: # 由增变减的拐点,作为区间的起点和终点 18 increasing = False 19 inflection_point.append(i) 20 elif steps[i] < steps[i + 1]: 21 increasing = True 22 i += 1 23 if increasing: 24 inflection_point.append(len(step) - 1) 25 26 # 舍弃被淹没在水下的拐点 27 i = 1 28 while i < len(inflection_point) - 1: 29 if steps[inflection_point[i - 1]] > steps[inflection_point[i]] < steps[inflection_point[i + 1]]: 30 inflection_point.pop(i) 31 else: 32 i += 1 33 34 # 遍历拐点区间,求出水量 35 for i in range(len(inflection_point) - 1): 36 level = min(steps[inflection_point[i]], steps[inflection_point[i + 1]]) # 水位 37 for j in range(inflection_point[i] + 1, inflection_point[i + 1]): 38 if level > steps[j]: 39 water += level - steps[j] 40 return water 41 42 43 44 if __name__ == '__main__': 45 steps = [1,2,3,4,5,6,7] 46 print steps, step_water(steps) # 0 47 48 steps = [7,6,5,4,3,2,1] 49 print steps, step_water(steps) # 0 50 51 steps = [3,1,4,5,1,6,7,2] 52 print steps, step_water(steps) # 6 53 54 steps = [4,1,0,5,5,3,2,7,7] 55 print steps, step_water(steps) # 12 56 57 steps = [5,1,3,1,5] 58 print steps, step_water(steps) # 10
延伸:
图像处理领域通常使用分水岭算法(watershed)如降雨法(rainfall)和淹没法(flooding)来找出分水线[1]。
Update-20131102:
这是Twitter笔试题,参见[2]。
参考资料:
1. http://en.wikipedia.org/wiki/Watershed_(image_processing)
2. http://qandwhat.apps.runkite.com/i-failed-a-twitter-interview/