炎炎夏日,還是呆在空調房里切切題吧。
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 With Most Water/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 With Most Water/O(n).js