2024.3.(15,16号)力扣刷题记录-相向双指针练习

一、18. 四数之和

相向双指针,参考灵神代码(. - 力扣(LeetCode)),特别是优化部分很神。代码如下:

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        n = len(nums)
        ans = []
        nums.sort()
        if n < 4:
            return ans

        for a in range(n-3):
            if a > 0 and nums[a] == nums[a-1]:     # 去重
                continue

            if nums[a]+nums[a+1]+nums[a+2]+nums[a+3] > target:    # 优化
                return ans
            if nums[a]+nums[-1]+nums[-2]+nums[-3] < target:
                continue

            for b in range(a+1,n-2):
                if b>a+1 and nums[b] == nums[b-1]:
                    continue

                if nums[a]+nums[b]+nums[b+1]+nums[b+2] > target:   #优化
                    break
                if nums[a]+nums[b]+nums[-1]+nums[-2] < target:
                    continue

                c,d = b+1,n-1
                while c<d:
                    if c>b+1 and nums[c] == nums[c-1]:    # 去重
                        c += 1
                        continue
                    if d < n-1 and nums[d] == nums[d+1]:
                        d -= 1
                        continue
                    
                    cur = nums[a]+nums[b]+nums[c]+nums[d]
                    if cur == target:
                        ans.append([nums[a],nums[b],nums[c],nums[d]])
                        c+=1    # 注意这里两个指针均需改变
                        d-=1
                    elif cur > target:
                        d -= 1
                    else:
                        c += 1
        return ans

二、611. 有效三角形的个数

相向双指针:

当时我没有想到遍历大的数,就使用的同向双指针,后面看了灵神题解(. - 力扣(LeetCode))才反应过来,枚举最大边,就变成了a+b > target的题目了,就能使用相向双指针来达到目的。另外增加了两个优化,代码如下:

class Solution:
    def triangleNumber(self, nums: List[int]) -> int:
        # 相向双指针
        nums.sort()
        n = len(nums)
        ans = 0
        for c in range(n-1,1,-1):
            if nums[c-2]+nums[c-1] <= nums[c]:  #优化
                continue
            if nums[0]+nums[1] > nums[c]:
                ans += c*(c-1)//2
                continue
            a,b = 0,c-1
            while a<b:
                if nums[a]+nums[b] > nums[c]:
                    ans += b-a
                    b -= 1
                else:
                    a += 1
        return ans

三、42. 接雨水

1.分层遍历(但是超时了)

思路:将它一层一层地看,记录单层接水量然后相加。虽然我已经做了优化了,但是时复毕竟是O(n^2),又1 <= n <= 2 * 10^4,所以还是超时了。代码如下:

class Solution:
    def trap(self, height: List[int]) -> int:
        # 超时
        maxhigh = max(height)
        ans = 0
        flag = 0    #记录是不是每一层第一次出现的
        a,b = 0,len(height)-1   # 优化,记录每一次最左最右范围
        for i in range(1,maxhigh+1):
            for j in range(a,b+1):
                if height[j] >= i:
                    if flag == 0:
                        flag = 1
                        a = j
                    else:
                        ans += j-1-foreidx
                    foreidx = j     #上一个出现的坐标
                    b = j
            flag = 0
        return ans

2.前后缀分解

学习视频:盛最多水的容器 接雨水_哔哩哔哩_bilibili

class Solution:
    def trap(self, height: List[int]) -> int:
        # 前后缀分解
        # 时复O(n),空复O(n)
        n = len(height)
        pre_max = [0]*n
        pre_max[0] = height[0]
        for i in range(1,n):
            pre_max[i] = max(pre_max[i-1],height[i])

        suf_max = [0]*n
        suf_max[-1] = height[-1]    # 逆序遍历,逆序输入
        for i in range(n-2,-1,-1):
            suf_max[i] = max(suf_max[i+1],height[i])

        ans = 0
        for h, pre, suf in zip(height,pre_max,suf_max):
            ans += min(pre,suf) - h
        return ans

2024.3.16续:

3.相向双指针

方法来自学习视频。太妙了!!!!(土拨鼠尖叫!!!!)

class Solution:
    def trap(self, height: List[int]) -> int:
        # 相向双指针 时复O(n),空复O(1)
        n = len(height)
        ans = 0
        l,r = 0,n-1
        pre_max = 0
        suf_max = 0
        while l<r:
            pre_max = max(pre_max, height[l])
            suf_max = max(suf_max, height[r])
            if pre_max < suf_max:
                ans += pre_max - height[l]
                l += 1
            else:
                ans += suf_max - height[r]
                r -= 1
        return ans

感谢你看到这里!一起加油吧!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值