鍍金池/ 教程/ Java/ Container With Most Water(最大水容器)
ZigZag Conversion(Z型轉(zhuǎn)換)
String to Integer (atoi)(轉(zhuǎn)換到整型)
Generate Parentheses(生成括號(hào))
Longest Common Prefix(最長(zhǎng)公共前綴)
Remove Duplicates from Sorted Array(從已排序數(shù)組中移除重復(fù)元素)
Swap Nodes in Pairs(交換序列中的結(jié)點(diǎn))
Valid Parentheses(有效的括號(hào))
4 Sum(4 個(gè)數(shù)的和)
3 Sum(3 個(gè)數(shù)的和)
3 Sum Closest(最接近的 3 個(gè)數(shù)的和)
Reverse Nodes in k-Group(在K組鏈表中反轉(zhuǎn)結(jié)點(diǎn))
Regular Expression Matching (正則表達(dá)式匹配)
Two Sum
Container With Most Water(最大水容器)
Merge Two Sorted Lists(合并兩個(gè)已排序的數(shù)組)
Remove Nth Node From End of List(從列表尾部刪除第 N 個(gè)結(jié)點(diǎn))
String to Integer (atoi)(轉(zhuǎn)換到整型)
Palindrome Number(回文數(shù))
Longest Substring Without Repeating Characters
Roman to Integer(羅馬數(shù)到整型數(shù))
Integer to Roman(整型數(shù)到羅馬數(shù))
Reverse Integer(翻轉(zhuǎn)整數(shù))
Merge k Sorted Lists(合并 K 個(gè)已排序鏈表)
Implement strStr()(實(shí)現(xiàn) strStr() 函數(shù))
Longest Palindromic Substring(最大回文子字符串)
Add Two Numbers
Letter Combinations of a Phone Number(電話號(hào)碼的字母組合)

Container With Most Water(最大水容器)

翻譯

給定 n 個(gè)非負(fù)整數(shù) a1,a2,...,an,其中每個(gè)代表一個(gè)點(diǎn)坐標(biāo)(i,ai)。

n 個(gè)垂直線段例如線段的兩個(gè)端點(diǎn)在(i,ai)和(i,0)。

找到兩個(gè)線段,與 x 軸形成一個(gè)容器,使其包含最多的水。

備注:你不必傾倒容器。

原文

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

n vertical lines are drawn
such that the two endpoints of line i is at (i, ai) 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.

題目的意思是,數(shù)組中的每個(gè)數(shù)對(duì)應(yīng)一條線段的長(zhǎng)度,索引對(duì)應(yīng) x 坐標(biāo),兩個(gè)索引可以組成一個(gè)底部的寬,高度就是前面所說(shuō)的線段的長(zhǎng)度,而既然是要盛水,高度就是兩個(gè)線段中較短的一個(gè)。

那么該怎么去解題呢?

我水平不行,英文也不行,所以每次一開(kāi)始都是用最簡(jiǎn)單的方法,旨在試試有沒(méi)有理解題目的意思,即便超出時(shí)間 / 空間限制也沒(méi)事。

public int MaxAera(int[] height)
{
    int area = 0;
    for (int i = 0; i < height.Length; i++)
    {
        for (int j = i + 1; j < height.Length; j++)
        {
            if (height[i] < height[j])
                area = Math.Max(area, countArea(height, i, j));
        }
    }
    return area;
}

public int countArea(int[] height, int x, int y)
{
    int h = height[x] > height[y] ? height[x] : height[y];
    int info = h * (y - x);
    return info;
}

很明顯這樣是不行的……

那有那些部分可以簡(jiǎn)化呢?

前面的方法是從數(shù)組左側(cè)開(kāi)始逐個(gè)向右遍歷所有情況,但明顯可以從兩側(cè)向中間進(jìn)發(fā),通過(guò)對(duì)應(yīng)的 max 函數(shù)來(lái)保留最大的面積。

當(dāng)從左邊進(jìn)入到圖中線段 1 位置,右邊進(jìn)入到線段 5 的時(shí)候。你不會(huì)想著右邊繼續(xù)進(jìn)入線段 6 和 7,因?yàn)槟憔褪菑哪沁呥^(guò)來(lái)的。

那么是該左邊的往右走,還是右邊的往左走呢?

如果是右邊的往左走,雖然線段 1 變成了線段 2,但是線段1到線段5的距離比線段 2 大,因此面積也大。所以走了之后面積反而小了。

如果是右邊的往左走,親自行腦補(bǔ):線段 3 和線段 4 是在同一位置,如果是到了線段 4,那么容器的高度將從原本的線段 5 的長(zhǎng)度變成線段 1 的長(zhǎng)度,(雖然由于距離的變小,總面積仍可能變小,但請(qǐng)繼續(xù)往下看),而如果到了線段 3,雖然高度變小了,寬度變小了,但,那又何妨呢?因?yàn)槟愕?maxArea 還是在那里的,每次的計(jì)算后,當(dāng)且僅當(dāng)高度超過(guò)原本的高度之后才會(huì)覆蓋原來(lái)的值。

maxArea = Max(maxArea,newArea);

也就是說(shuō),高度如果沒(méi)有超過(guò),就沒(méi)有什么影響。

http://wiki.jikexueyuan.com/project/leetcode-book/images/2.png" alt="" />

至于你說(shuō)它會(huì)不會(huì)因?yàn)樽栽龊妥詼p而發(fā)生越界,如果

int[] height = {10, 1, 2, 3, 4, 5, 6, 7, 11};

假設(shè)這里的 10 和 11 對(duì)應(yīng)線段 1 和線段 6,請(qǐng)自行腦補(bǔ):去掉線段 7,既然線段 1 短于線段 6,那么發(fā)生的是 left++,而不是 left–。所以,并不會(huì)越界的。反之,亦然。

public class Solution
{
    public int MaxArea(int[] height)
    {
        int left = 0, right = height.Length - 1;
        int maxArea = 0;
        while (left < right && left >= 0 && right <= height.Length - 1)
        {
            maxArea = Math.Max(maxArea, Math.Min(height[left], height[right]) * (right - left));
            if (height[left] > height[right])
            {
                right--;
            }
            else
            {
                left++;
            }
        }
        return maxArea;
    }
}

明天繼續(xù),加油!