炎炎夏日,还是呆在空调房里切切题吧。

Container With Most Water,题意其实有点噱头,简化下就是,给一个数组,恩,就叫 height 吧,从中任选两项 i 和 j(i <= j),使得 Math.min(height[i], height[j]) * (j - i) 最大化,求解这个最大值。

O(n^2)

O(n^2) 复杂度的解法非常容易想到,直接两两枚举。

var maxArea = function(height) {
  var len = height.length;
  var maxn = 0;

  for (var i = 0; i < len; i++)
    for (var j = i + 1; j < len; j++)
      maxn = Math.max(maxn, Math.min(height[i], height[j]) * (j - i));

  return maxn;
};

提交,TLE,看了下数据,数组长度 1w,复杂度直接飙到亿级,不 TLE 才怪了。

O(nlogn)

我们假设数组为 [a1, a2, ..., an],我们实际需要求得的其实是一个子数组。假设这个子数组的最后一个元素是 a5,同时我们规定该子数组最后一个元素不大于第一个元素,那么实际我们需要求的是 a1, a2, a3, a4 中哪个元素比 a5 大(或者相同),并且这个元素越前面越好。

这样,我们可以遍历每个元素,将这个元素确定为子数组的最后一个元素,同时去求前面已经被遍历过的元素中,大于等于该元素并且最左的元素。对于求这个最左元素,我们可以维护一个单调递增的数组,用二分去解。

二分需要求解一个递增序列中,刚好大于等于指定元素的位置,这个 case 没有出现在 二分查找大集合(妈妈再也不用担心我的二分查找了),我们可以稍微变个形。

// 求解 a 数组中刚好大于等于 target 的位置
// 如果都小于 target 则返回 a.length
function binarySearch(a, target) {
  target += 1;
  var start = 0
    , end = a.length - 1;

  while(start <= end) {
    var mid = ~~((start + end) >> 1);
    if (a[mid] >= target)
      end = mid - 1;
    else
      start = mid + 1;
  }

  if (a[start - 1] === target - 1)
    start -= 1;
  return start;
}

还需要注意的一点是,必须正反来两次,因为我们假设子数组的最后一个元素小于等于首元素,还需要考虑另一种情况,即子数组首元素小于等于最后一个元素。

其他部分问题不大,具体代码可以参考 https://github.com/hanzichi/leetcode/blob/master/Algorithms/Container%20With%20Most%20Water/O(nlogn).js

提交,AC,击败 4% ... 势必还有更优的解法,而且根据我的经验,如果这是标程正解的话,这道题的难度应该是 Hard 而不是 Medium 了。

O(n)

正解的复杂度应该是 O(n) 的。

我们可以举个简单的例子,假设数组是 [2, 3, 4, 5, 4, 3],那么最长的子数组一定只有一个,即取全部元素,这样能装的水的数量是 2 * 5 。接下去我们的子元素,长度一定是会变小的,有两种情况,为 [2, 3, 4, 5, 4] 和 [3, 4, 5, 4, 3]。我们来看 [2, 3, 4, 5, 4],这种情况下,显然比取全部元素求得的结果 10 要小,为什么这么说?因为两者的基准都是按 2 来算的,但是取全部元素长度大。

似乎有点眉目了,再来看 [2, 3, 4, 5, 4, 3] 这个原始的数组,从中找出一个子数组,如果以 2 为子数组最左的元素,那么这个子数组求解的值(即装水的量),不可能比 [2, 3, 4, 5, 4, 3] 这个原始数组求到的 10 要大了,有木有?!因为该子数组装水的基准,是不可能比 2 大了的。

这样,我们似乎可以用一点点贪心去解这道题,一步步缩小子数组的大小。

while (start <= end) {
  maxn = Math.max(maxn, Math.min(height[end], height[start]) * (end - start));

  if (height[end] < height[start])
    end --;
  else
    start ++;
}

完整代码可以参考 https://github.com/hanzichi/leetcode/blob/master/Algorithms/Container%20With%20Most%20Water/O(n).js

如何装最多的水? — leetcode 11. Container With Most Water的更多相关文章

  1. [LeetCode] 11. Container With Most Water My Submissions Question 解题思路

    Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai).  ...

  2. leetcode 11. Container With Most Water 、42. Trapping Rain Water 、238. Product of Array Except Self 、407. Trapping Rain Water II

    11. Container With Most Water https://www.cnblogs.com/grandyang/p/4455109.html 用双指针向中间滑动,较小的高度就作为当前情 ...

  3. Leetcode 11. Container With Most Water(逼近法)

    11. Container With Most Water Medium Given n non-negative integers a1, a2, ..., an , where each repr ...

  4. [LeetCode] 11. Container With Most Water 装最多水的容器

    Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). ...

  5. 蜗牛慢慢爬 LeetCode 11. Container With Most Water [Difficulty: Medium]

    题目 Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai ...

  6. LeetCode 11. [👁] Container With Most Water & two pointers

    盛最多水的容器 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找 ...

  7. LeetCode 11. Container With Most Water (装最多水的容器)

    Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai).  ...

  8. [leetcode]11. Container With Most Water存水最多的容器

    Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). ...

  9. [LeetCode]11. Container With Most Water 盛最多水的容器

    Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). ...

随机推荐

  1. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

  2. python 学习笔记 -logging模块(日志)

    模块级函数 logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root loggerlogging.debug().logging.info().lo ...

  3. Android 手机卫士8--删除通话记录

    1.编写代码需要注意bug: 再删除通话记录的时候,删除的是以前的通话记录,本次拦截下来的电话号码,通话记录没有删除?????? 问题原因:数据库中本次通话记录的电话号码还没有插入,就做了删除操作 2 ...

  4. List Set Map

    List Set 都是接口,都继承了Collection接口 ArrayList LinkList 直接实现了List接口 HashSet 实现了Set接口  TreeSet继承父类AbstractS ...

  5. 批量处理sql 数据存入xml类型列

    个人记录 需求:当表T1 ItemCode和表T2 ItemName的数据相等时,将表T2所对应的ID和ItemName列的数据分别存入表T1 CAOZUO字段的id元素和text元素的文本中. 下面 ...

  6. 使用WebRTC搭建前端视频聊天室——入门篇

    http://segmentfault.com/a/1190000000436544 什么是WebRTC? 众所周知,浏览器本身不支持相互之间直接建立信道进行通信,都是通过服务器进行中转.比如现在有两 ...

  7. 阶段一:通过网络请求,获得并解析JSON数据(天气应用)

    “阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 在上一篇阶段一:解析JSON中提到,最近在写一个很简单的天气预报应用.即使功能很简单,但我还是想把它做成一个相对完 ...

  8. 安卓开发之ListAdapter(二)

    今天我们来学习一下ArrayAdapter: ArrayAdapter是安卓中最简单的适配器.使用ArrayAdapter(数组适配器),需要把数据源存 放至数组里面来显示. •构造函数: publi ...

  9. 【译】Spring 4 自动装配、自动检测、组件扫描示例

    前言 译文链接:http://websystique.com/spring/spring-auto-detection-autowire-component-scanning-example-with ...

  10. ITIS-资料集合贴

    ITIS-资料集合贴 说明:这个贴用于收集笔者能力范围内收集收藏并认为有用的资料,方便各方参考,免去到处找寻之苦,提升信息的交叉引用价值.另外,笔者就自己感悟做了部分评注,且可能尝试不断的优化分类和排 ...