盛水最多的容器

67 阅读5分钟

盛水最多的容器

给定 n 个非负整数,其中每个代表坐标处的一个点。绘制 n 条垂直线,如下图所示:

找到两条线,它们与 x 轴一起形成一个容器,使得该容器包含最多的水。 该程序应返回一个整数,该整数对应于可容纳的最大水面积(最大面积而不是最大体积听起来很奇怪,但为了简单起见,这里我们使用 2D 平面)。

注意:容器不得倾斜。

例子 :

Input: array = [1543]
Output: 6
Explanation :
5 and 3 的横向距离是 2.
最小高度 = min(5, 3) = 3.
So total area = 3 * 2 = 6.

Input: array = [31245]
Output: 12
Explanation :
5 and 3 的横向距离是 4.
最小高度 = min(5, 3) = 3.
So total area = 4 * 3 = 12

天真的解决方案:

  • 方法:这个想法非常简单,检查每对边界,并找出任意对边界下的最大面积。
  • 算法:
    • 创建一个嵌套循环,外层循环从0到end遍历数组(本次循环的索引为i)。
    • 内循环从i+1开始遍历数组到end(该循环的索引是j)。
    • 求边界高度为 array[i] 和 array[j] 的容器中可容纳的水,即面积 = (j – i)* min(array[i],array[j]),如果面积大于当前最大值,更新当前最大值
  • 打印当前最大值。

C++

// C++ code for Max
// Water Container
#include <iostream>
using namespace std;

int maxArea(int A[], int len)
{
    int area = 0;
    for (int i = 0; i < len; i++) {
        for (int j = i + 1; j < len; j++) {
            // Calculating the max area
            area = max(area, min(A[j], A[i]) * (j - i));
        }
    }
    return area;
}

// Driver code
int main()
{
    int a[] = { 1543 };
    int b[] = { 31245 };

    int len1 = sizeof(a) / sizeof(a[0]);
    cout << maxArea(a, len1);

    int len2 = sizeof(b) / sizeof(b[0]);
    cout << endl << maxArea(b, len2);
}

Java

// Java code for Max
// Water Container
import java.io.*;

class GFG{

public static int maxArea(int[] a)
{

    int Area = 0;

    for(int i = 0; i < a.length; i++)
    {
        for(int j = i + 1; j < a.length; j++)
        {
            Area = Math.max(
                Area, Math.min(a[i], a[j]) *
                              (j - i));
        }
    }
    return Area;
}

// Driver code
public static void main(String[] args)
{
    int a[] = { 1543 };
    int b[] = { 31245 };

    System.out.println(maxArea(a));
    System.out.println(maxArea(b));
}
}

Python

# Python3 code for Max
# Water Container
def maxArea(A, Len) :
    area = 0
    for i in range(Len) :
        for j in range(i + 1, Len) :

            # Calculating the max area
            area = max(area, min(A[j], A[i]) * (j - i))
    return area

# Driver code
a = [ 1543 ]
b = [ 31245 ]

len1 = len(a)
print(maxArea(a, len1))

len2 = len(b)
print(maxArea(b, len2))

C#

// C# code for Max
// Water Container
using System;
class GFG
{

public static int maxArea(int[] a)
{

    int Area = 0;

    for(int i = 0; i < a.Length; i++)
    {
        for(int j = i + 1; j < a.Length; j++)
        {
            Area = Math.Max(Area, Math.Min(a[i], a[j]) *
                            (j - i));
        }
    }
    return Area;
}

// Driver code
public static void Main(String[] args)
{
    int []a = { 1543 };
    int []b = { 31245 };

    Console.WriteLine(maxArea(a));
    Console.Write(maxArea(b));
}
}

Javascript

<script>
    // Javascript code for Max
    // Water Container

    function maxArea(A, len)
    {
        let area = 0;
        for (let i = 0; i < len; i++) {
            for (let j = i + 1; j < len; j++) {
                // Calculating the max area
                area = Math.max(area, Math.min(A[j], A[i]) * (j - i));
            }
        }
        return area;
    }

      let a = [ 1543 ];
    let b = [ 31245 ];

    let len1 = a.length;
    document.write(maxArea(a, len1) + "</br>");

    let len2 = b.length;
    document.write(maxArea(b, len2));

</script>

输出:

6
12

复杂度分析:

  • 时间复杂度:O(n^2)。 由于需要对数组进行嵌套遍历,所以时间复杂度为O(n^2)
  • 空间复杂度:O(1)。 由于不需要额外的空间,因此空间复杂度是恒定的。

高效的解决方案:

  • 保留两个索引,first = 0和last = n-1以及一个存储最大面积的值max_area。
  • 运行循环,直到前索引first大于等于后索引last。
  • 使用 max_area 和 min(array[first] , array[last])*(last-first) 中的最大值更新 max_area
  • 如果array[first]的值大于array[last],则将last更新为last – 1,否则将first更新为first + 1
  • 打印最大面积。

下面的 GIF 解释了该方法

ezgif.com-gif-maker3.gif

C++

// C++ code for Max
// Water Container
#include<iostream>
using namespace std;

int maxArea(int A[], int len)
{
    int l = 0;
    int r = len -1;
    int area = 0;

    while (l < r)
    {
        // Calculating the max area
        area = max(area, min(A[l],
                        A[r]) * (r - l));

            if (A[l] < A[r])
                l += 1;

            else
                r -= 1;
    }
    return area;
}

// Driver code
int main()
{
    int a[] = {1543};
    int b[] = {31245};

    int len1 = sizeof(a) / sizeof(a[0]);
    cout << maxArea(a, len1);

    int len2 = sizeof(b) / sizeof(b[0]);
    cout << endl << maxArea(b, len2);
}

Java

// Java code for Max
// Water Container
import java.util.*;

class Area{

    public static int maxArea(int A[], int len)
    {
        int l = 0;
        int r = len -1;
        int area = 0;

        while (l < r)
        {
            // Calculating the max area
            area = Math.max(area,
                        Math.min(A[l], A[r]) * (r - l));

            if (A[l] < A[r])
                l += 1;

            else
                r -= 1;
        }
        return area;
    }

    public static void main(String[] args)
    {
        int a[] = {1543};
        int b[] = {31245};

        int len1 = 4;
        System.out.print( maxArea(a, len1)+"\n" );

        int len2 = 5;
        System.out.print( maxArea(b, len2) );
    }
}

Python

# Python3 code for Max
# Water Container
def maxArea( A):
    l = 0
    r = len(A) -1
    area = 0

    while l < r:
        # Calculating the max area
        area = max(area, min(A[l],
                        A[r]) * (r - l))

        if A[l] < A[r]:
            l += 1
        else:
            r -= 1
    return area

# Driver code
a = [1543]
b = [31245]

print(maxArea(a))
print(maxArea(b))

C#

// C# code for Max
// Water Container
using System;

class Area{

    public static int maxArea(int []A, int len)
    {
        int l = 0;
        int r = len -1;
        int area = 0;

        while (l < r)
        {
            // Calculating the max area
            area = Math.Max(area,
                        Math.Min(A[l], A[r]) * (r - l));

            if (A[l] < A[r])
                l += 1;

            else
                r -= 1;
        }
        return area;
    }

    // Driver code
    public static void Main()
    {
        int []a = {1543};
        int []b = {31245};

        int len1 = 4;
        Console.WriteLine( maxArea(a, len1));

        int len2 = 5;
        Console.WriteLine( maxArea(b, len2) );
    }
}

PHP

<?php
// PHP code for Max
// Water Container
function maxArea($A$len)
{
    $l 0;
    $r $len -1;
    $area 0;

    while ($l $r)
    {
        // Calculating the max area
        $area max($areamin($A[$l],
                    $A[$r]) * ($r $l));

            if ($A[$l] < $A[$r])
                $l += 1;

            else
                $r -= 1;
    }
    return $area;
}

// Driver code
$a array(1543);
$b array(31245);

$len1 sizeof($a) / sizeof($a[0]);
echo maxArea($a$len1). "\n";

$len2 sizeof($b) / sizeof($b[0]);
echo maxArea($b$len2);

?>

Javascript

<script>

// Javascript code for Max
// Water Container
function maxArea(A, len)
{
    let l = 0;
    let r = len -1;
    let area = 0;

    while (l < r)
    {

        // Calculating the max area
        area = Math.max(area, Math.min(A[l],
                        A[r]) * (r - l));

        if (A[l] < A[r])
            l += 1;
        else
            r -= 1;
    }
    return area;
}

// Driver code
let a = [ 1543 ];
let b = [ 31245 ];

let len1 = a.length;
document.write(maxArea(a, len1) + "</br>");

let len2 = b.length;
document.write(maxArea(b, len2));


</script>

输出

6
12

复杂度分析:

  • 时间复杂度:O(n)。 由于只需要遍历一次数组,所以时间复杂度为O(n)。
  • 空间复杂度:O(1)。 不需要额外的空间,因此空间复杂度是恒定的。

解决方案分析 – 为什么这个解决方案有效?

在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 −1 变短:

  • 若向内 移动短板 ,水槽的短板 min(h[i],h[j]) 可能变大,因此下个水槽的面积 可能增大.
  • 若向内 移动长板 ,水槽的短板 min(h[i],h[j]) 不变或变小,因此下个水槽的面积 一定变小.
  • 因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积.