经典面试题:计算积水的横截面积

原题:给定一个整数数组,假设元素都是厚为1的挡板,往里面倒水,计算盛水的最大横截面积。 算法1思路:

  1. 实现思路:每次看到一个元素,就往回看会增加多少积水
  2. 时间复杂度,每遍历一个元素都有可能回看所有已经出现的元素,所以是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组数据的模拟,大家可以肉眼验证其正确性

转载于:https://my.oschina.net/rst/blog/531497

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值