[LeetCode]Container With Most Water

題目:Container With Most Water數組

給定一個int數組,找到兩個值,以其下標的差爲寬度,最短高度爲高度求面積。app

思路:this

定義兩個指針,一個從前日後,一個從後往前;spa

每次固定前面的指針,後面的遍歷一遍找到最大的面積(和前面的循環結果比較)記錄下來。指針

/***************************************************************************
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 and n is at least 2.
***************************************************************************/
#include <stdio.h>

int maxArea(int* height, int heightSize) {
    int maxi = 0,max = 0;
    int curh = 0,cur = 0;
    for(int i = 0;i < heightSize;i++){
        if(height[i] <= maxi)continue;//當後續搜索的height比以前的小時,因爲寬度(i->j)在減少,面積不可能比當前最優值還好,因此捨棄
        maxi = height[i];
        for(int j = heightSize - 1;j > i;j--){
            curh = height[i] > height[j] ? height[j] : height[i];
            cur = curh*(j - i);
            if(cur > max){
                max = cur;
            }
            if(curh == height[i])break;//噹噹前獲得的面積的高度是height[i]時,繼續搜索因爲寬度減少,且高度不會超過height[i],因此放棄
        }
    }
    return max;
}

int main(){
    int h[] = {2,4,3,2,1};
    int maxA = maxArea(h,5);
    printf("%d\n",maxA);
}

還有複雜度O(n)的作法。code

一樣定義和上面同樣的指針,要求最大面積,指針移動時寬度會減少,因此要儘可能找最小高度更大的,orm

因此每次比較兩個指針的高度,最小的若是是前面的指針,則右移一位,不然後面的指針左移一位。blog

這樣保證高度是遞增的形式。get

int maxArea(vector<int>& height){
    int area = 0;
    auto head = height.begin();
    auto end = height.begin();
    end += height.size() - 1;
    while (head != end){
        int temp;//記錄當前面積
        if ((*head) >= (*end)){
            temp = (*end)*(end - head);
            --end;
        }
        else{
            temp = (*head)*(end - head);
            ++head;
        }
        if (temp > area)area = temp;
    }
    return area;
}

題目:Product of Array Except Self it

給定一個數組,數組大小大於1,求數組除了每一個位置外元素的積;

For example, given [1,2,3,4], return [24,12,8,6] = [2*3*4,1*3*4,1*2*4,1*2*3].

要求:不能用除法,且時間複雜度O(n),空間複雜度O(1)。

思路:

正常狀況,能夠直接求數組全部元素的積,而後除以每一個元素就能輕鬆求出結果,可是不能用除法;

也可使用輔助的數組保存兩兩的乘積,而後再擴充乘積,也許也能求解,可是這都不符合要求。

假設數組A[] = {a1,a2,a3,a4,a5,a6}

那麼結果R[] = {  a2*a3*a4*a5*a6,

        a1*a3*a4*a5*a6,

      a1*a2*a4*a5*a6,

    a1*a2*a3*a5*a6,

  a1*a2*a3*a4*a6,

a1*a2*a3*a4*a5}

將上面的結果分爲兩部分發現前半是數組中1-5項的階乘,後半是數組中2-6項的階乘。

這樣就可以不適用輔助數組,從頭至尾,再從尾到頭,遍歷兩次就能獲得結果。

vector<int> LeetCode::productExceptSelf(vector<int>& nums){
    vector<int>result(nums.size());//Pi = a0*a1*...*ai-1*ai+1*ai+2*...*an
    int product = 1, index = 1;
    result.at(0) = 1;
    for (size_t i = 0; i < nums.size() - 1; ++i){//Pi = a0*a1*...*ai-1,跳過第一個元素
        product *= nums.at(i);
        result.at(index++) = product;
    }
    product = 1;
    index = index - 2;
    for (size_t i = nums.size() - 1; i > 0; --i){//Pi = an*an-1*...*ai+1,跳過最後一個元素
        product *= nums.at(i);
        result.at(index) *= product;
        --index;
    }
    return result;
}

題目:Trapping Rain Water

給定表示每一個條的寬度爲1的高度圖的n個非負整數,計算下雨後可以收集的水量。

For example, 
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

思路:

用棧保存有效高度的下標,遍歷高度數組,當數組值大於0時,作一下比較:

  1. 當前高度比棧頂高度小,求出可盛水的容量,water = (i - s.top())*height[i];並將當前高度入棧
  2. 當前高度比棧頂高度大,求出可盛水的容量,並將棧頂元素出棧,而後接着比較當前高度和棧頂高度,直到棧空或比棧頂高度小時,當前高度入棧;

例如:height{0,0,5,0,3,4,2,7,0,6}

當遍歷到3的時候,棧s{5},3<5,求容量並將3入棧;

當遍歷到4的時候,棧s{5,3},4>3,求容量,並將3出棧,而後比較4<5,再求面積(此時高度爲4 - 3),將4入棧;

int LeetCode::trap(vector<int>& height){
    stack<int>s;
    int water = 0;//裝水量
    int i = 0;//height下標
    while (i < height.size() && !height.at(i))++i;//找到第一個大於0的高度
    s.push(i++);
    while (!s.empty() && i < height.size()){
        while (i < height.size() && !height.at(i))++i;//找到下一個大於0的高度
        if (i >= height.size())break;
        int pre = s.top();
        if (height.at(pre) > height.at(i)){//當前高度比棧頂高度小,求出可盛水的容量,併入棧
            water += (i - pre - 1)*height.at(i);
            s.push(i);
        }
        else{//當前高度比棧頂高度大,求出可盛水的容量,並出棧,直到棧空或比棧頂高度小時,入棧
            water += (i - pre - 1)*height.at(pre);
            s.pop();
            while (!s.empty() && height.at(s.top()) <= height.at(i)){//直到棧空或當前高度比棧頂高度小
                water += (i - s.top() - 1)*(height.at(s.top()) - height.at(pre));//pre的高度入棧時已經求過
                pre = s.top();
                s.pop();
            }
            if(!s.empty())water += (i - s.top() - 1)*(height.at(i) - height.at(pre));//pre的高度入棧時已經求過
            s.push(i);
        }
        ++i;
    }
    return water;
}
相關文章
相關標籤/搜索