leetcode不按期刷題---11.盛最多水的容器

11.盛最多水的容器

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/probl...數組

給定 n 個非負整數 a1,a2,...,an,每一個數表明座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別爲 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器能夠容納最多的水。spa

說明:你不能傾斜容器,且 n 的值至少爲 2。指針

示例圖

圖中垂直線表明輸入數組 [1,8,6,2,5,4,8,3,7]。在此狀況下,容器可以容納水(表示爲藍色部分)的最大值爲 49。code

示例:blog

輸入: [1,8,6,2,5,4,8,3,7]
輸出: 49

題解:遞歸

一:暴力法

看到這題,像我這樣的通常第一時間想到的就是暴力法,雙層循環,列舉出全部的可能性,而後選出最大的一個值。ip

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
  let newS = 0;
  for(let i = 0; i < height.length;i++){
    for(let j = i+1;j<height.length;j++){
        newS = Math.max(newS,Math.min(height[i],height[j])*(j-i))
    }
  }
  return newS;
};

複雜度分析

時間複雜度:O(n^2),計算全部 n(n−1)/2種高度組合的面積。內存

空間複雜度:O(1),使用恆定的額外空間。leetcode

執行結果

執行用時 :948 ms, 在全部 JavaScript 提交中擊敗了29.18%的用戶rem

內存消耗 :35.3 MB, 在全部 JavaScript 提交中擊敗了73.30%的用戶

明顯能夠感覺到暴力法通常都不是最優解。

二.雙指針

矩形的面積是長和寬相乘,若是要面積大,那麼長和寬要儘量的長。

在這題裏,矩形的寬就是h(i)h(j)的距離,就是(j-i),而寬則是h(i)h(j)中較短的那一條。那麼要面積儘量的大,就須要Math.min(h(i),h(j))儘可能大,(j-i)儘可能大。

咱們設置兩個指針 leftright,分別指向數組的最左端和最右端。此時,兩條垂直線的距離是最遠的,若要下一個矩陣面積比當前面積來得大,必需要把 height[left]height[right]中較短的垂直線往中間移動,看看是否能夠找到更長的垂直線。

由於將較長的那根垂直線往中間移動,面積只會減少,因此移動較短的那根。

將全部的狀況用遞歸樹列出來,以下圖:

IMG_9099.JPG

數組是 [1,8,6,2,5,4,8,3,7]

指針在兩端,沒進行一次比較就能劃去一列不可能的選項。以下圖,當比較第一次的時候,h(0)h(8)比較,此時的面積是h(0)*(8-0)=8,那麼就須要劃掉跟0相關的那一列,由於那一列的面積確定只會比8小。以下圖:

1

而後比較下一級h(1)和h(8),從而得出面積是49,由於h(1)>h(8),因此能夠劃去跟h(8)相關的一列,由於面積不管怎麼樣都會小於(1,8),以下圖

2

以此類推,最終獲得一條路線。

IMG_9099的副本.JPG

在比較的時候就把最大值存入一個變量中,而後在結束的時候返回就行。

var maxArea = function(height) {
    let maxS = 0;
    let i = 0,j = height.length-1;
    while(i < j){
      maxS = Math.min(height[i],height[j])*(j-i)>maxS?Math.min(height[i],height[j])*(j-i):maxS;
      height[i] <= height[j] ? i++ : j--
    }
    return maxS;
  };

執行用時 :64 ms, 在全部 JavaScript 提交中擊敗了97.97%的用戶

內存消耗 :35.2 MB, 在全部 JavaScript 提交中擊敗了85.63%的用戶

相關文章
相關標籤/搜索