一枚菜鸟的leetcode刷题笔记 - Day 3

15 - 三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        ans = []
        n = len(nums)

        for p1 in range(n):
            if p1 > 0 and nums[p1] == nums[p1-1]:
                continue
            p3 = n-1
            for p2 in range(p1+1,n):
                if p2 > p1+1 and nums[p2] == nums[p2-1]:
                    continue
                while p2 < p3 and nums[p2] + nums[p3] > -nums[p1]:
                    p3 -= 1
                if p2 == p3:
                    break
                if nums[p2] + nums[p3] == -nums[p1]:
                    ans.append([nums[p1], nums[p2], nums[p3]])
        return ans

完全参考了官方解法:三数之和

最开始只能想到暴力, O ( n 3 ) O(n^3) O(n3),看了题解get了排序+双指针,把第二和第三重循环糅合到一块。
这题要注意避免重复,通过排序可以避免[a,b,c],[b,a,c],[c,b,a]…这类情况出现,此外排序后的列表利用if p1 > 0 and nums[p1] == nums[p1-1]也可以避免重复数字重复计算
最终的时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1)

其实代码都不是一步就写得好的,都是慢慢优化来的,可以逐渐在最容易想到的方法上优化。

11 - 盛最多水的容器

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。

class Solution:
    def maxArea(self, height: List[int]) -> int:
        p1, p2 = 0, len(height)-1
        ans = (p2 - p1) * min(height[p1], height[p2])
        while p1 < p2:
            temp = (p2 - p1) * min(height[p1], height[p2])
            if temp > ans:
                ans = temp
            if height[p1] < height[p2]:
                p1 += 1
            else:
                p2 -= 1
        return ans

又是看官方答案才写出来的,我为什么只能想到暴力。。。盛最多水的容器

这题我感觉考的是分析,双指针这个方法只是手段。最重要的是要分析出规律,比如

  1. 为什么两个指针要设在列表头尾,其他位置不行吗?
    这样做是为了保证顺序,因为从两边向中间遍历时,p2-p1的值是减小的,这样结合移动值小的指针,就可以保证 O ( n ) O(n) O(n)时间内找到最优解
  2. 为什么每次移动的是值小的指针?
    反过来想,若移动值较大的指针,min(height[p1], height[p2])不会有什么改善甚至更糟,p2-p1也变得更小了,毫无疑问不会有什么改善,所以只能移动值较小的指针看看会不会有突破

上面两点分析使得直接可以去掉一重循环。
我发现双指针在趣掉多余的循环上很有帮助,但更重要的是分析。

14 - 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。
0 <= strs.length <= 200

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if not strs:
            return ''
        maxStr = strs[0]
        for s in strs:
            temp = ''
            for j in range(min(len(s),len(maxStr))):
                if s[j] == maxStr[j]:
                    temp += maxStr[j]
                else:
                    break
            maxStr = temp
        return maxStr

依次扫描字符串列表的每一项,维护一个maxStr记录当前最大公共前缀,每次用新的字符串和maxStr比较并更新maxStr。当扫描完整个列表,即得到答案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值