Leetcode——Container With Most Water

题目简介

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,其中每一个都表示坐标系(i,ai)中的一个点。上面画了n个垂线,起点是(i,0),终点是(i,ai)。找到两根线,组成一个容器,这个容器能装最多的水

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

容器的四个边不能是斜的
在这里插入图片描述

The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.

思路分析——暴力求解

  • 原则分析:

在这里插入图片描述

  • 当以一条边为基准边的时候,只用选择距离其最远的而且比起高或者相等
    的边,即可找到以当前边构成的最大的容器

  • 不可能以最高的边构成基准边

  • 按照从简入繁的原则去分析解决问题
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 基本原则
    • 每条边都对应一个最大的容器,比较所有边构成的容器即可,选出最大的边
    • 为了简化计算,将所有的点按照高度从小到大排序,那么每一次比较仅仅需要比较排在其后面的边即可选出

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int maxArea(int *height,int heightSize);

int main()
{
    
    
    //今日分leetcode
    int a[] = {
    
    1,8,6,2,5,4,8,3,7};
    printf("%d\n",maxArea(a,9));
    return 0;
}

int maxArea(int *height,int heightSize)
{
    
    
    int container = 0,temp = 0,containertemp = 0;
    //所有的边对应的最大的容器
    for(int i = 0;i < heightSize;i ++)
    {
    
    
        //对应某一个边,选出某一个边的对应的最大的容器
        for(int j = 0;j < heightSize;j ++)
        {
    
    
            //首先必须比当前的边要高并且距离要是最远
            if(height[i] <= height[j] && abs(j - i) >= temp)
            {
    
    
                temp = abs(j - i);
            }
        }
        containertemp = temp * height[i];
        if(containertemp >= container)
        {
    
    
            container = containertemp;
        }
        temp = 0;
    }
    return container;
}

分析总结

  • 运行超时,归因于多增加了一倍的比较量。不应该以某一个边为基准边,应去找比起高的别的边,构成以该边为边的最大的矩形。应该列出所有的两两组合,然后计算两两组合的面积,进而相比较。

借鉴学习——摘自https://leetcode.com/problems/container-with-most-water/discuss/6099/yet-another-way-to-see-what-happens-in-the-on-algorithm

Draw a matrix where rows correspond to the position of the left line, and columns corresponds to the position of the right line.

画一个矩阵,矩阵的行代表容器的左边线,矩阵的列代表容器的右边那条线

For example, say n=6. Element at (2,4) would corresponds to the case where the left line is at position 2 and the right line is at position 4. The value of the element is the volume for the case.

例如:n = 6,总共有六条线,点(2,4)代表的情况是,左边线在2,右边线在4. 该点的值就代表这种情况下容器的面积

In the figures below, x means we don’t need to compute the volume for that case, because:

在如下的数据中,x代表我们不需要计算这些情况下的容器的面积,因为:

  • on the diagonal, the two lines are overlapped;

对角线表示两条线重合,不能构成容器

  • the lower left triangle area of the matrix, the two lines are switched and the case is symmetric to the upper right area.

矩阵左边三角形与矩阵右部分的三角形只需要取一部分,二者是相对称。以a边为左边,b边为右边,和以b边为左边,a边为右边是相似的,这是一个组合问题,不是排序问题。

We start by computing the volume at (1,6), denoted by o. Now if the left line is shorter than the right line, then moving the right line towards left would only decrease the volume, so all the elements left to (1,6) on the first row have smaller volume. Therefore, we don’t need to compute those cases (crossed by —).

我们开始计算(1,6)出的面积,记为o。现在如果左边的边比右边更短,然后将右边的边向左移动,仅仅会减少容器的面积,所以(1,6)左边的所有的在第一行的所有的点都会有一个更小的值。因此,我们不需要计算那些点对应的面积,用-标记

 1 2 3 4 5 6
1 x ------- o
2 x x
3 x x x 
4 x x x x
5 x x x x x
6 x x x x x x

So we can only move the left line towards right to 2 and compute (2,6). Now if the right line is shorter, all cases below (2,6) are eliminated.

所以,我们仅仅能把左边的边向右边2移动,计算(2,6),现在如果右边的边是短的,所有的在点(2,6)下面的情况都不可取,都将被淘汰

 1 2 3 4 5 6
1 x ------- o
2 x x       o
3 x x x     |
4 x x x x   |
5 x x x x x |
6 x x x x x x

And no matter how this o path goes, we end up only need to find the max value on this path, which contains n-1 cases.

最终无论o的路径是什么样的,我们仅仅需要找到这条路径上的最大值,总共包含n- 1种情况

 1 2 3 4 5 6
1 x ------- o
2 x x - o o o
3 x x x o | |
4 x x x x | |
5 x x x x x |
6 x x x x x x
  • 总结:
    • 两边构成图形,短边决定实际长度,两边相距决定实际的宽度
    • 不动短边动长边,宽度减少,长变更短,则变本加厉,长更减少。所以不动长边动短边。
    • 记录所有可能的点,然后比较

代码实现

int maxArea(int *height,int heightSize)
{
    
    
    int i = 0 ,j = heightSize - 1, container = 0 ,temp = 0;
    for(;i <= j;)
    {
    
    
        temp = 0;
        if(height[i] < height[j])
        {
    
    
            temp = height[i] * (j - i);
            i ++;
        }
        else
        {
    
    
            temp = height[j] * (j - i);
            j --;
        }
        if(container < temp)
        {
    
    
            container = temp;
        }
    }
    return container;
}

猜你喜欢

转载自blog.csdn.net/Blackoutdragon/article/details/108165906