力扣42.接雨水-python解法总结

解法一:暴力无脑解题法(超时)

对每一个格子进行推算,根据左右最高的格子数来计算能接水的单位数,最后逐一相加

class Solution:
    def trap(self, height: List[int]) -> int:
        ans = 0
        for i in range(len(height)):
            max_left, max_right = 0,0
            # 寻找 max_left
            for j in range(0,i):
                max_left = max(max_left,height[j])
            # 寻找 max_right
            for j in range(i,len(height)):
                max_right = max(max_right,height[j])
            if min(max_left,max_right) > height[i]:
                ans += min(max_left,max_right) - height[i]    
        return ans

解法二:动态规划

在暴力解题的基础上,使用数组来放置maxleft和maxright,降低时间复杂度,遍历次数大大减少

class Solution:
    def trap(self, height: List[int]) -> int:
        # 边界条件
        if not height: return 0
        n = len(height)
        maxleft = [0] * n
        maxright = [0] * n
        ans = 0
        # 初始化
        maxleft[0] = height[0]
        maxright[n-1] = height[n-1]
        # 设置备忘录,分别存储左边和右边最高的柱子高度
        for i in range(1,n):
            maxleft[i] = max(height[i],maxleft[i-1])
        for j in range(n-2,-1,-1):
            maxright[j] = max(height[j],maxright[j+1])
        # 一趟遍历,比较每个位置可以存储多少水
        for i in range(n):
            if min(maxleft[i],maxright[i]) > height[i]:
                ans += min(maxleft[i],maxright[i]) - height[i]
        return ans

解法三:分层+双指针

接完雨水后的图形,看起来会有很明显的特点,从前后分别往中间靠,一定是递增的,一直到最高点

所以分设两个指针left,right,从前后分别向中间移动,在遇到较之前大的数字后停下,两个指针进行计算right-left+1得出这一层的单元块有多少个,然后将每一层的块数加起来,就是接水后的块数,再减去输入的块数,就是雨水的单位数,图解如下

class Solution:
    def trap(self, height: List[int]) -> int:
        n=len(height)
        left,right=0,n-1
        SUM,tmp,high=0,0,1
        while(left<=right):
            while(left<=right and height[left]<high):
                SUM+=height[left]
                left+=1
            while(right>=left and height[right]<high):
                SUM+=height[right]
                right-=1   
            high+=1
            tmp+=right-left+1      
        return tmp-SUM

解法四:双指针+几何法

另外解法三也可以改进一下,因为你会发现,如果两个指针相对移动的同时,分别记录遇到的最大值,然后每一轮都将他们的值相加,最后的结果会是以max(list)和len(list)为边长的矩形格子数加上接雨水后的图形,看下图

红线和黄线分别是left和right指针移动路线的值

class Solution:
    def trap(self, height: List[int]) -> int:
        lmax, rmax, res = 0, 0, 0
        for i in range(len(height)):
            lmax = max(lmax, height[i])
            rmax = max(rmax, height[-1-i])
            res += lmax + rmax - height[i]
        return res - lmax * len(height)

解法五:几何法

如图分成四个块,要求的是灰色部分的单位块数,由大矩形块数减去黑色部分也就是输入的列表的求和,再减去红色和淡蓝色的部分,这两部分分别是从前和后向中间遍历到最高点,记录最大值与最高点的差值

class Solution:
    def trap(self, height: List[int]) -> int:
        if not height: return 0
        max_h = max(height)
        rain = max_h * len(height) - sum(height)
        m_h = 0
        for h in height:
            if h >= max_h: break
            if h > m_h: m_h = h
            rain -= max_h - m_h
        m_h = 0
        for h in reversed(height):
            if h >= max_h: break
            if h > m_h: m_h = h
            rain -= max_h - m_h
        return rain

!!!本文参考了力扣大神的解法,特此说明!!!

### 力扣435题无重叠区间问题的Python解决方案 对于力扣435题——Non-overlapping Intervals,目标是从给定的一组区间中移除尽可能少的数量使得剩余区间互不重叠。一种高效的方法是采用贪心算法来解决这个问题。 为了有效地解决问题,可以先按照区间的结束位置升序排列这些区间[^1]。通过这种方式,在遍历时总是优先保留那些较早结束的区间,从而为后续可能加入更多非重叠区间留出空间。 下面是具体的Python实现代码: ```python class Interval(object): def __init__(self, start, end): self.start = start self.end = end def eraseOverlapIntervals(intervals): if not intervals: return 0 # Sort the intervals based on their ending time. sorted_intervals = sorted(intervals, key=lambda interval: interval.end) count = 0 prev_end = float('-inf') for current_interval in sorted_intervals: if current_interval.start >= prev_end: # If there is no overlap with previous selected interval, # update `prev_end` and continue without incrementing removals counter (`count`) prev_end = current_interval.end else: # Otherwise, this means we have an overlapping pair; # since intervals are already ordered by 'end', simply increase our removal tally (`count`) count += 1 return count ``` 此方法的时间复杂度主要取决于排序操作O(n log n),其中n表示输入区间的数量;而随后的一次线性扫描只需要O(n)时间。因此整体性能表现良好,适用于大多数实际应用场景中的数据规模[^2]。 值得注意的是,上述逻辑确保了每次遇到新的候选区间时都会选择最早结束的那个作为下一个非重叠部分的一部分,这样就能最大限度地减少被删除掉的区间数目[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值