• leetcode 11. 盛最多水的容器


    11. 盛最多水的容器

    难度中等

    给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

    说明:你不能倾斜容器。

    示例 1:

    输入:[1,8,6,2,5,4,8,3,7]
    输出:49 
    解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

    示例 2:

    输入:height = [1,1]
    输出:1
    

    示例 3:

    输入:height = [4,3,2,1,4]
    输出:16
    

    示例 4:

    输入:height = [1,2,1]
    输出:2
    

    提示:

    • n = height.length
    • 2 <= n <= 3 * 104
    • 0 <= height[i] <= 3 * 104

    法一:极其朴素的暴力解法(时间超限,中等题目用暴力就是作死)

    class Solution {
    public:
        int maxArea(vector<int>& height) {
            int n = height.size(), Max = 0;
            for(int i=0; i<n; i++){
                for(int j=1; j<n; j++){
                    Max = max(Max, (j-i)*min(height[i], height[j]));
                }
            }
            return Max;
            
        }
    };

    法二:双指针解法

    看了答案我哭了~

    思路:

    首先,明确一点,结果应该是max{min(height[j], height[i]) * (j-i)}。

    现在考虑设置两个指针i和j,分别指向首元素和尾元素。双指针代表的是可以作为容器左边界和右边界的范围。每次都把指向较小元素的那个指针指向下一个元素,就表示这个指针不可能再作为容器的边界了。在遍历过程中就能得到结果。

    为啥每次都把指向较小元素的那个指针指向下一个元素呢?

    不妨设height[i] 等于 x, height[j] = y, 且x<y. 那么,当前容器容量是min(height[j], height[i]) * (j-i) = x*(j-i);

    假设接下来j向左移,height[j-1] = y1. (j-i)一定会变小

    1、y1<=y,  min(height[j], height[i]) * (j-i)  = min(x, y1)*(j-i) <=  min(x, y)*(j-i)

    2、y1>y, min(height[j], height[i]) * (j-i)  = min(x, y1)*(j-i) = x*(j-i) = min(x,y)*(j-i)

     无论怎么移动右指针,得到的容器容量都小于前容器的容量。

    所以,我们应该移动height值较小的那个指针。

    class Solution {
    public:
        int maxArea(vector<int>& height) {
            int n = height.size(), Max = 0;
            int i = 0, j = n-1;
            while(i < j){
                Max = max(Max, min(height[i], height[j])*(j-i));
                if(height[i] < height[j]) i++;
                else j--;
    
            }
            return Max;
            
        }
    };

    法三: 动态规划

     递归法,可以改成法二迭代,这里主要理解思想。

    class Solution {
    public:
        int getResult(int l, int r, vector<int> &h){
            if(r-l == 1) return min(h[r], h[l]);
            int Max = min(h[r], h[l])*(r-l), subMax = 0;
            if(h[l] < h[r]){
                subMax = getResult(l+1, r, h);
            }
            else
                subMax = getResult(l, r-1, h);
            return max(Max, subMax);
        }
        int maxArea(vector<int>& height) {
            int n = height.size(), Max = 0;
            Max = getResult(0, n-1, height);
            return Max;
        }
    };
  • 相关阅读:
    SQL server 函数
    SQL server --时间日期函数、类型转换
    SQL server 基础知识
    14.C#的递归
    13.C#的函数练习
    使用bind部署DNS主从服务器
    创建yum仓库
    Linux基础服务搭建综合
    完整的URL是怎样的?
    mysqli_fetch_row()函数返回结果的理解
  • 原文地址:https://www.cnblogs.com/AbsolutelyPerfect/p/14685831.html
Copyright © 2020-2023  润新知