zoukankan      html  css  js  c++  java
  • LeetCode OJ 11. 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.

    【思路1】

    暴力拆解,找出所有的组合,返回其中最大的。但是这样运行会超时,代码如下:

     1 public class Solution {
     2     public int maxArea(int[] height) {
     3         if(height == null || height.length == 0) return 0;
     4         int max = 0;
     5         for(int i = 0; i < height.length - 1; i++){
     6             for(int j = i + 1; j < height.length; j++){
     7                 int minH = Math.min(height[i], height[j]);
     8                 max = Math.max(max, (j - i)*minH);
     9             }
    10         }
    11         return max;
    12     }
    13 }

    【思路2】

    The brute force solution can definitely lead us to the right answer just by doing too many redundant comparisons. When two pointer approach comes to mind, it is intuitive to set both pointers i, j at each end of this array, and move them strategically to the middle of array, update the answer during this process return the answer when we reach the end of array. Suppose now we have the scenarios below:

    7, 5, 6, 9
    
    i        j
    

    When i = 1, j = 4,

    ans = min(7, 9) * (4 - 1) = 21 
    

    What's next? Should we move i or j? We notice that to calculate the area, the height is really identified by the smaller number / shorter end between the two ends, since it's required that you may not slant the water, so it sounds like Bucket theory: how much water a bucket can contain depends on the shortest plank. So, as to find the next potential maximum area, we disregard the shorter end by moving it to the next position. So in the above case, the next status is to move i to the left,

    7, 5, 6, 9
    
       i     j
    

    update:

    area (i, j) = area(2, 4) = min(5, 9) * (4 - 2) = 10
    ans = max(21, 10) = 21
    

    You may notice that, if we move j instead, you actually get a larger area for length of 2:

    area (i, j) = area(1, 3) = min(7, 6) * (3 - 1) = 18
    

    Does that mean this approach will not work? If you look at this way, we move pointer as to get the next potential max, so it doesn't need to be the maximum for all combinations with length l. Even though 18 is greater than 10, it's smaller than 21 right? So don't worry, we can move on to find the next potential maximum result. Now we need to prove, why disregard the shorter end can safely lead us to the right answer by doing a little maths.

    Given an array: a1, a2, a3, a4, ai, ......, aj, ......, an
                                     i           j
    

    Assume the maximum area so far is ans, we prove that

    "By moving shorter end pointer further doesn't eliminate the final answer (with two ends at maxi, maxj respectively) in our process"
    

    Suppose we have two ends at (i, j) respectively at this moment:

    (i) If the final answer equals what we have already achieved, it's done! In this scenario, we must have

    maxi <= i, maxj >= j 
    

    (ii) Otherwise, we know as we move any pointer further, the length of the next rectangle decreases, so the height needs to increase as to result in a larger area. So we have

    min(height[maxi], height[maxj]) > min(height[i], height[j]) 
    

    So the smaller one in height[i], height[j] won't become any end in the maximum rectangle, so it's safe to move forward without it.

    Till now, it has been proved that this approach can work in O(n) time since we advance one end towards the middle in each iteration, and update ans takes constant time in each iteration.

    代码如下:

     1 public class Solution {
     2     public int maxArea(int[] height) {
     3         int ans = 0;
     4         int i = 0, j = height.length - 1;
     5         while(i < j){
     6             ans = Math.max(ans, (j - i) * Math.min(height[i], height[j]));
     7             if(height[i] > height[j]) j--;
     8             else i++;
     9         }
    10 
    11         return ans;
    12     }
    13 }
  • 相关阅读:
    WMS、WCS、PLC、AGV
    SAP消息号修改汇总
    SQL 计算累计和 sum() over( partition by order by )
    DDLS报错数据类型冲突:data type conflict in a selection 解决办法
    SAP销售订单需求类型的确定优先级
    SAP替代,出口U904在RGGBS000中未生成
    订单BOM与销售BOM的区别
    在配置和销售凭证 GET_CONFIG_MODE 间通信时内部出错
    ABAP Write
    php的api接口
  • 原文地址:https://www.cnblogs.com/liujinhong/p/5517660.html
Copyright © 2011-2022 走看看