原题:给定一个整数数组,假设元素都是厚为1的挡板,往里面倒水,计算盛水的最大横截面积。 算法1思路:
- 实现思路:每次看到一个元素,就往回看会增加多少积水
- 时间复杂度,每遍历一个元素都有可能回看所有已经出现的元素,所以是O(n^2)
def cal_water(array):
if not array: return 0
rtv, max_v = 0, array[0]
for idx, value in enumerate(array[1:]):
ridx = idx
local_max = array[ridx]
while value > local_max and local_max != max_v:
rtv += min(value, max_v) - local_max
ridx -= 1
local_max = max(local_max, array[ridx])
max_v = max(max_v, value)
return rtv
算法2思路: 1.实现思路,找到最大元素,然后分北坡和南坡计算积水面积
2.时间复杂度NlogN
def south_area(arr, idx):
if idx <= 1:
return 0
i = idx - 1
south_index, south_max = i, arr[i]
while i >= 0:
if arr[i] > south_max:
south_index, south_max = i, arr[i]
i -= 1
rtv = 0
i = south_index
while i < idx:
rtv += south_max - arr[i]
i += 1
return rtv + south_area(arr, south_index)
def north_area(arr, idx):
if idx >= len(arr) - 1:
return 0
i = idx + 1
north_index, north_max = i, arr[i]
while i < len(arr):
if arr[i] > north_max:
north_index, north_max = i, arr[i]
i += 1
rtv = 0
i = north_index
while i > idx:
rtv += north_max - arr[i]
i -= 1
return rtv + north_area(arr, north_index)
def water_area(arr):
if len(arr) <= 1:
return 0
max_index, max_value = 0, arr[0]
for index, value in enumerate(arr):
if value > max_value:
max_index, max_value = index, value
return south_area(arr, max_index) + north_area(arr, max_index)
测试用例
for i in range(20):
array = random.sample(range(20), random.randint(1, 20))
print 'array: ', array
print 'cal_water: ', cal_water(array)
print 'water_area: ', water_area(array)
print '================================='
此处进行了10组数据的模拟,大家可以肉眼验证其正确性