11 leetcode - Container with most water

转载请标明来源(http://blog.csdn.net/lis_12/article/details/53178870

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
英文:
Given n non-negative integers a1, a2, ..., an,
where each represents a point at coordinate (i, ai).
n vertical lines are drawn such that the two endpoints of line i is
at (i, ai) and (i, 0). Find two lines,
which together with x-axis forms a container,
such that the container contains the most water.
中文:给n个非负数a1, a2, ..., an,让(ix,ax),(iy,ay)与x轴组成容器,求容器最大容量
'''
class Solution(object):
    def maxArea1(self, height):#常见方法,时间复杂度O(n*n)
        """
        :type height: List[int]
        :rtype: int
        """
        length = len(height)
        if length < 2:
            return 0
        max_area = 0
        for i in range(length):
            for j in range(i+1,length):
                area = (j - i) * min(height[i],height[j])
                if area > max_area:
                    max_area = area
        return max_area

    def maxArea(self,height):#时间复杂度O(n)
        length = len(height)
        if length < 2:
            return 0
        max_area = start = 0
        end = length - 1
        while start < end:
            max_area = max(max_area,(end - start) * min(height[end],height[start]))
            if height[start] <= height[end]:#横向不断变小的同时,只有竖向不断变大才可能超过之前的值
                start += 1
            else:
                end -= 1

        return max_area

if __name__ == "__main__":
    s = Solution()
    print s.maxArea([1,2,1])

时间复杂度O(n)代码说明

  1. 木桶容量取决于两边中较短的边,而且如果将较短的边换为更短边的话,容量只会变少;

  2. 因为S = (x1 - xn) * min(y1,yn),当(x1 - xn)越来越小,min(y1,yn)越来越大,S才可能变大;

方法

用两个指针从两端开始向中间靠拢,如果左端线段短于右端,那么左端右移,反之右端左移,知道左右两端移到中间重合,记录这个过程中每一次组成木桶的容积,返回其中最大的就为最大盛水量。解释如下。

例子

解释

  1. 当height[L] < height[R]时,L与R左侧线段组成的木桶为什么没必要判断呢?

    当左端线段height[L]小于右端线段height[R]时,我们将L右移,这时舍弃的是L与R左侧线段(R+1, R+2, …{R左侧的线段})组成的木桶,这些木桶是没必要判断的,因为这些木桶的容积肯定都没有L和R组成的木桶容积大。

    为什么R+1, R+2, …与L组成的木桶肯定没有L和R组成的木桶容积大呢?

    因为当左端线段L小于右端线段R,L较短,不管R+1, R+2…是否大于R,竖向最大值就为L,而且横向R - L最大,所以R+1, R+2, …与L组成的木桶肯定都没有L和R组成的木桶容积大。

  2. 当height[L] < height[R]时,L与R右侧线段组成的木桶为什么也没必要判断呢?

    当height[L] < height[R],height[L]那么减小肯定不会使水的容量增大,只有height[L]增加才有可能使水的容量增大。

    但是会不会有这种可能:当前的L 和 某个k (k ∈ R-1,R-2...{R右侧线段})组成的木桶是最大容量呢?肯定是不可能啊= =….

    因为按照移动规则,既然右指针从k 移动到了R,说明L的左边一定存在一个边界 j,使height[j] > height[k],那么[j, k]的容量肯定大于[L, k],所以[L,k]不可能是最大容量,L与R右侧的线段组成的木桶没有必要判断。

    (通俗版:右侧能移动到R说明L左侧肯定存在一个大于height[k]的线段j,[j,k]的容量肯定大于[L,k],所以L与R右侧的线段组成的木桶肯定不是最大容量。)

​ 综上所述,上述方法求解最大容量的方法正确。

继续优化

上述方法是可以优化的,不过没太大意义。。。

具体查找步骤:

  1. R1 < L1,向R1左侧寻找比R1大的值,比R1还小的没有比较的意义 ,因为S1 = (x_R1 - x_L1) * R1,横向不断减小,竖向还减小的话,肯定没有S1大;
  2. R2 > L1,同理,向L1右侧寻找比L1大的值;
  3. 重复直至两侧重合。

参考网址:

  1. http://blog.csdn.net/wzy_1988/article/details/17248209
  2. http://blog.csdn.net/ljiabin/article/details/41673753
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值