算法--Container With Most Water

Given n non-negative integers a1a2, ..., an , where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

给定一个数组,求出能够包含容量最大的一个矩形区域的起始坐标。

假定矩形区域的左右短点为i,j  则矩形区域的面积  min(height[i], height[j]) *(j-i)  (i<j)

笨办法遍历所有情况:  时间复杂度N2

def maxArea(height=[1,8,6,2,5,4,8,3,7]):
    """
    :type height: List[int]
    :rtype: int
    """
    r = 0
    for i in range(0,len(height)-1):
        for j in range(i+1,len(height)):
            print(i, j, (min(i,j))*(j-i))
            r = max(r, min(height[i],height[j])*(j-i))
    print(r)
    return r

利用双指针,分别从左右端点进行遍历求解,矩形区域的面积与端点距离以及端点值的最小值决定,初始化i=0 j=len-1,此时端点距离最大,而min(height[i],height[j])未必是所有情况最大的,现在开始搜索下一种情况可能会比初始值更大的情况,i增加,j减少时,端点距离减少,但是最小值可能会增加,因此矩形面积可能也会增加。

s = min(height[i], height[j]) *(j-i)  (i<j)   当i,j由初始情况变化时,j-i必定会减少,现在要使s增大,则要使min(height[i], height[j])变大,显然其值由较小值决定,因此应该移动较小值来试探下一个可能的s较大值。

def maxArea2(height=[1,8,6,2,5,4,8,3,7]):
    """
    :type height: List[int]
    :rtype: int
    """
    i = 0
    j = len(height)-1
    r = 0
    while i<j:
       r = max(r, min(height[i],height[j])*(j-i))
       if height[i]<height[j]:
           i += 1
       else:
           j -= 1
    print(r)
    return r

下面是大神的解释:

假定数组元素共有6个,则i,j的取值一共有36中组合情况,其中i==j为零不需要计算  i>j与i<j是对称的,因此只需要计算一半即可。构建一个矩阵,行表示左指针i的取值,列表示右指针j的取值: x表示不需要计算  o表示最优值的探索路径  ---表示可以直接跳过的取值集合,要求最优值,即遍历所有i,j取值组合,利用s = min(height[i], height[j]) *(j-i)  (i<j) 求出最大值即可。一般情况遍历所有取值组合需要N2复杂度,现在要利用左右端点较小值,来优化搜索路径:

初始情况,i<j  即只需要搜索所有对角线右上组合即可,初始时(1,6)此时若左端点值小于右端点值,则(1,2:5)则不需要搜索,因为此时容量由较小值左端点决定,移动右端点并不能优化最大值

当height[i]<height[j]时,执行i++  搜索位置(2,6) 若此时右端点小于左端点,移动左端点并不能增大面积,因此(3:5,6)可以不用搜索

height[j]<height[i]时,j--

依次遍历,最终结果相当于搜索i,j所有取值组合,即一定可以搜索到最优值,并且时间复杂度为O(N).

猜你喜欢

转载自blog.csdn.net/u014106644/article/details/84134220