算法总结(1)--最大储水量相关算法题(栈,优先队列模拟)

来源:互联网 发布:mac怎么裁剪音乐 编辑:程序博客网 时间:2024/04/27 15:16

最大储水量相关算法题
在leetcode,牛客网上类似的题目比较多,主要用到了栈,还有就是一些求解思路的问题(去掉一些无用的结果),这样降低时间复杂度

==

涉及到动态规划栈模拟优先队列等,主要是如何舍弃一些无用的结果

考虑时间复杂度从O(n^2)降到O(nlogn)再到O(n)等,包括使用hash

直方图内最大矩形

题目地址:

http://www.nowcoder.com/practice/13ba51c3fec74b58bbc8fa8c3eedf877?tpId=49&tqId=29284&rp=1&ru=/ta/2016test&qru=/ta/2016test/question-ranking

题目描述

有一个直方图,用一个整数数组表示,其中每列的宽度为1,求所给直方图包含的最大矩形面积。比如,对于直方图[2,7,9,4],它所包含的最大矩形的面积为14(即[7,9]包涵的7x2的矩形)。
给定一个直方图A及它的总宽度n,请返回最大矩形面积。保证直方图宽度小于等于500。保证结果在int范围内。
测试样例:
[2,7,9,4,1],5
返回:14

求解

求直方图矩形面积的最大值就是求数组中相邻元素(单个元素,两两相邻,三三相邻。。。 )中最小值乘以他们的数量得到面积,再取最大值,

  • 可以直接O(n^2)求解,找到前面的位置和后面一个位置

  • 利用栈,维持一个递增序列,当遇到小的直方图后,回退,依次求解

ac代码:

class MaxInnerRec {public:    // 2 7 9 4 1 ,5 返回 14    int countArea(vector<int> A, int n) {        if(n == 0)            return 0;        int maxVal = A[0];        stack<int> sta;        sta.push(A[0]);        for (int i = 1; i < n; i++)        {            int topVal = sta.top();            if (A[i] > topVal)            {                sta.push(A[i]);            }            else{                int cnt = 0;                while (!sta.empty() && sta.top() > A[i])                {                    cnt++;                    int popVal = sta.top();                    sta.pop();                    int popMax = popVal*cnt;// 9 * 1, 7 * 2                    if (popMax > maxVal)                    {                        maxVal = popMax;                    }                }                // 2 7 9 4 变成 2 4 4 4                // 2 4 4 4 1 变成 1 1 1 1 1, 计算出4*1, 4*2, 4*3, 2*4                for (int j = 0; j < cnt + 1; j++)                    sta.push(A[i]);            }        }        int cnt = 0;        while(!sta.empty())        {            cnt ++;            int popVal = sta.top();            sta.pop();            int popMax = popVal*cnt;            if (popMax > maxVal)            {                maxVal = popMax;            }        }        return maxVal;    }};

11. Container With Most Water

题目地址

https://leetcode.com/problems/container-with-most-water/

题目描述

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.

求解思路

找两条竖线,与x轴组成一个容器,能存水的最大值

采用前后指针法

class Solution {public:    int maxArea(vector<int> &height) {        int i = 0;        int j = height.size() - 1;        int ans = 0;        while (i < j)        {            int area = (j - i) * min(height[i], height[j]);            ans = max(ans, area);            // 舍弃短的,知道两条竖线相遇            if (height[i] <= height[j])                i++;            else                j--;        }        return ans;    }};

42. Trapping Rain Water

题目地址

https://leetcode.com/problems/trapping-rain-water/

题目描述

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

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

求解思路

利用栈,大致思路是,在栈上维持一个最大值,如果比当前最大值小的全部入栈,遇到大的,可以进行一次存储水了,然后更新最大值继续操作。最后如果栈不为空,需要按照原来的思路,反过来再对其求解。最后可得到最终结果

class Solution {public:    int trap(vector<int>& height) {        int len = height.size();        if (len < 3)            return 0;        stack<int> sta;        sta.push(height[0]);        int maxH = height[0];        int ans = 0;        for (int i = 1; i < len; i++){            if (height[i] < maxH){                sta.push(height[i]);            }            else{                //                 while (!sta.empty()){                    int val = sta.top();                    sta.pop();                    ans += maxH - val;                }                sta.push(height[i]);                maxH = height[i];            }        }        stack<int> sta2;        if (!sta.empty()){            maxH = sta.top();            sta.pop();            sta2.push(maxH);        }        while (!sta.empty()){            int tmp = sta.top();            sta.pop();            if (tmp < maxH){                sta2.push(tmp);            }            else{                //                 while (!sta2.empty()){                    int val = sta2.top();                    sta2.pop();                    ans += maxH - val;                }                sta2.push(tmp);                maxH = tmp;            }        }        return ans;    }};

407. Trapping Rain Water II

题目地址:

https://leetcode.com/problems/trapping-rain-water-ii/

题目描述

Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining.

Note:
Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000.

Example:

Given the following 3x6 height map:

[  [1,4,3,1,3,2],  [3,2,1,3,2,4],  [2,3,3,2,3,1]]

Return 4.

在上一题的基础上,变成了一个三维的。

 求解思路

维持一个优先队列,每次都取高度最低的那个,从外围到内,队列的出队列和入队列,确保所有位置都能试探一遍,然后添加访问标识,并在求解过程中修改高度值

ac代码

// 代码参考:http://blog.csdn.net/MebiuW/article/details/52664669?locationNum=1class Cell{public:    int x, y, h;    Cell(int _x, int _y, int _height){        x = _x;        y = _y;        h = _height;    }};struct cmp{    bool operator()(Cell c1, Cell c2)    {        return c1.h > c2.h;    }};class Solution {public:    int trapRainWater(vector<vector<int>>& heightMap) {        int m = heightMap.size();        if (m == 0)            return 0;        int n = heightMap[0].size();        if (n == 0)            return 0;        priority_queue<Cell,vector<Cell>,cmp> pq; // 每次取出的都是高度最小的        vector<vector<bool>> vis;        vis.resize(m, vector<bool>(n,false));        //a.resize(m, vector<int>(n));        for (int i = 0; i < m; i++){            vis[i][0] = true;            vis[i][n-1] = true;            Cell c1(i, 0, heightMap[i][0]);            Cell c2(i, n-1, heightMap[i][n-1]);            pq.push(c1);            pq.push(c2);        }        for (int j = 0; j < n; j++)        {            vis[0][j] = true;            vis[m-1][j] = true;            Cell c1(0, j, heightMap[0][j]);            Cell c2(m-1, j, heightMap[m-1][j]);            pq.push(c1);            pq.push(c2);        }        int ans = 0;        int dir[][2] = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };        while (!pq.empty())        {            Cell cell = pq.top();            pq.pop();            for (int i = 0; i < 4; i++)            {                int nx = cell.x + dir[i][0];                int ny = cell.y + dir[i][1];                if (nx >= 0 && nx < m && ny >= 0 && ny < n && !vis[nx][ny])                {                    vis[nx][ny] = true;                    ans += max(0, cell.h - heightMap[nx][ny]); // 这里注意                    Cell ctmp(nx, ny, max(heightMap[nx][ny], cell.h));                    pq.push(ctmp);                }            }        }        return ans;    }};
0 0
原创粉丝点击