【leet-code】接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]

输出: 6

分析:

解法1:暴力法

对每个元素取其左右两边的最大值的最小值,然后减去当前值

时间复杂度:O(N^2),对每个元素都需要取其左右两边的最大值

空间复杂度:O(1)

class Solution
{
public:
    int trap(vector<int>& v)
    {
        int ans=0;
        if(v.size()==0)
            return 0;
        for(int i=1; i<v.size()-1; i++)
        {
            int leftmax=0;
            for(int j1=i-1; j1>=0; j1--) //取其左边元素的最大值
            {
                leftmax=max(leftmax,v[j1]);
            }
            int rightmax=0;
            for(int j2=i+1; j2<v.size(); j2++) //取其右边元素的最大值
            {
                rightmax=max(rightmax,v[j2]);
            }
            int x=min(leftmax,rightmax)-v[i];//取两个最大值的最小值
            if(x>0)//能够储水
            {
                ans+=x;//符合要求则加上
            }
        }
        return ans;
    }
}

解法2:动态规划

暴力法每次都有寻找其左右两边最大元素的最小值

我们可以通过两次O(N)的遍历记录下当前元素的左右两边最大值的最小值

时间复杂度:O(N)

空间复杂度:O(N)

class Solution
{
public:
    int trap(vector<int>& v)
    {
        int ans=0;
        if(v.size()==0)
            return 0;
        int n=v.size();
        int dp[n];//dp[i]:当前元素i左右两边最大值的最小值
        dp[0]=0;
        dp[n-1]=0;

        for(int i=1; i<n-1; i++) //左边最大值
        {
            dp[i]=max(dp[i-1],v[i-1]);
        }
        for(int i=n-2; i>=1; i--) //右边最大值和当前左边最小值比较
        {
            dp[i]=min(dp[i],max(dp[i+1],v[i+1]));
        }
        for(int i=1; i<n-1; i++) //符合要求累加即可
        {
            if(dp[i]-v[i]>0)
                ans+=dp[i]-v[i];
        }
        return ans;
    }
}

解法3:左右双指针法

先找到最高点k,k把数组分为了左右两部分

对左半部分的当前值来说:

如果当前值大于当前值左边的最大值,那么水就会向左边流走,当前值就储存不了水,只能更新一下左边最大值

如果当前值不大于当前值左边的最大值,那么就可以储存住水,水的量就是当前左边最大值减去当前值

对右半部分的当前值来说:

如果当前值小于当前值右边的最大值,那么水就会向右边流走,当前值就储存不了水,只能更新一下右边最大值

如果当前值不大于当前值右边的最大值,那么就可以储存住水,水的量就是当前右边最大值减去当前值

注意,左边最大值和右边最大值都不是相对于整个左边部分或右边部分来说的

左边最大值是相当于当前元素的左边的所有元素来说的

右边最大值是相当于当前元素的右边的所有元素来说的

时间复杂度:O(N)

空间复杂度:O(1)

class Solution
{
public:
    int trap(vector<int>& v)
    {
        int ans=0;
        int n=v.size();
        if(n==0)
            return 0;
        int k=0;
        for(int i=1; i<n; i++) //找到最高点k,k把数组分为左右两部分(都不包含k)
        {
            if(v[i]>v[k])
                k=i;
        }
        int maxleft=0;//左边最大值指针
        for(int i=1; i<k; i++) //左半部分
        {
            if(v[maxleft]<v[i])//不能储水,水向左边流走了
                maxleft=i;//更新左边最大值
            else
                ans+=(v[maxleft]-v[i]);//可以储存水
        }
        int maxright=n-1;//右边最大值指针
        for(int i=n-2; i>k; i--) //右半部分
        {
            if(v[maxright]<v[i])//不能储存水。水向右边流走了
                maxright=i;//更新右边最大值
            else
                ans+=(v[maxright]-v[i]);//可以储存水
        }
        return ans;
    }
}

原文地址:https://www.cnblogs.com/yinbiao/p/11611552.html

时间: 2024-10-16 10:58:27

【leet-code】接雨水的相关文章

#Leet Code# Evaluate Reverse Polish Notation

描述:计算逆波兰表达法的结果 Sample: ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 ["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6 使用stack实现: 1 def is_op

#Leet Code# Unique Tree

语言:Python 描述:使用递归实现 1 class Solution: 2 # @return an integer 3 def numTrees(self, n): 4 if n == 0: 5 return 0 6 elif n == 1: 7 return 1 8 else: 9 part_1 = self.numTrees(n-1) * 2 10 part_2 = 0 11 12 for i in range(1,n-1): 13 part_left = self.numTrees(

leet code Sort List

*/--> pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} leet code Sort List 对链表使用快慢指针归并排序 Sort List Sort a linked list in O(n log n) time using constant space complexity. /** * Definition for singly-lin

#Leet Code# Sqrt

描述:log(n) 代码: 1 class Solution: 2 # @param x, an integer 3 # @return an integer 4 def getVal(self, begin, end, x): 5 if end == begin : 6 return begin 7 if end == begin + 1: 8 return begin 9 10 while True: 11 mid = (begin + end) / 2 12 tmp = mid * mid

【Leet Code】Palindrome Number

Palindrome Number Total Accepted: 19369 Total Submissions: 66673My Submissions Determine whether an integer is a palindrome. Do this without extra space. 判断一个数整数是不是回文?例如121,1221就是回文,好吧,直接利用前面写过的[Leet Code]Reverse Integer--"%"你真的懂吗? 不过这里要考虑翻转后,数值

Leet Code OJ 119. Pascal&#39;s Triangle II [Difficulty: Easy]

题目: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3, Return [1,3,3,1]. Note: Could you optimize your algorithm to use only O(k) extra space? 翻译: 给定一个下标k,返回第k行的杨辉三角. 例如给定k=3,返回[1,3,3,1]. 提示:你可以优化你的算法,让它只使用O(k)的额

#Leet Code# Gray Code

描述: 要求相邻数2进制差一位 先获得n-1的列表表示小于 2^(n-1) 的符合要求的列表,加上最高位的加成 2^(n-1) 就是大于等于 2^(n-1) 的符合要求的列表,后者翻转一下就能够与前者连接上了 代码: 1 class Solution: 2 # @return a list of integers 3 def grayCode(self, n): 4 if n == 0: return [0] 5 6 s1 = self.grayCode(n - 1) 7 s2 = [item

Leet Code OJ 118. Pascal&#39;s Triangle [Difficulty: Easy]

题目: Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5, Return [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] 翻译: 给定一个数numRows,产生前numRows行的杨辉三角(即贾宪三角形.帕斯卡三角形). 分析: 除了每行首尾是1以外,其他元素均可由上行推出,本方案采用lastLine保存上行数

#Leet Code# Same Tree

语言:Python 描述:使用递归实现 1 # Definition for a binary tree node 2 # class TreeNode: 3 # def __init__(self, x): 4 # self.val = x 5 # self.left = None 6 # self.right = None 7 8 class Solution: 9 # @param p, a tree node 10 # @param q, a tree node 11 # @return

#Leet Code# LRU Cache

语言:C++ 描述:使用单链表实现,HeadNode是key=-1,value=-1,next=NULL的结点.距离HeadNode近的结点是使用频度最小的Node. 1 struct Node { 2 int key; 3 int value; 4 Node* next; 5 }; 6 7 class LRUCache { 8 public: 9 LRUCache(int capacity) { 10 this->capacity = capacity; 11 this->curLength