LeetCode算法题刷题笔记

文章目录

  • 简单来说
    • 简单
      • #1 - 两数之和
        • 题干
        • 解题
    • 中等
      • [#15 - 三数之和](https://leetcode-cn.com/problems/3sum/)
        • 题干
        • 解题
    • 困难
      • [#10 - 正则表达式匹配](https://leetcode-cn.com/problems/regular-expression-matching/)
        • 题干
        • 解题
    • 总结

简单来说

勇敢的你,站在这里,脸庞青涩却骄傲。

简单

#1 - 两数之和

题干

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解题

easy game

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            if target-nums[i] in nums:
                for j in range(i+1,len(nums)):
                    if target-nums[i] == nums[j]:
                        return [i,j]
        return [-1,-1]

中等

#15 - 三数之和

题干

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

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
 [-1, 0, 1],
 [-1, -1, 2]
]

解题

看到题目,首先想到 ab 剪枝,于是作答如下:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res = []
        dictDeleteRepeat = {}
        lastNum = None
        for i in range(len(nums)-2):
            if lastNum!=nums[i]:
                # 剪枝
                leftValue = 0-nums[i]
                lastNumInner = None
                if leftValue<=nums[-1]+nums[-2] and leftValue>=nums[i + 1]+nums[i + 2]:
                    for j in range(i+1,len(nums)-1):
                        if lastNumInner!=nums[j]:
                            # 再剪
                            leftValueInner = leftValue-nums[j]
                            if leftValueInner<=nums[-1] and leftValueInner>=nums[j + 1]:
                                if leftValueInner in nums[j+1:]:
                                    tempList = [nums[i],nums[j],leftValueInner]
                                    listStr = ''.join([str(item) for item in tempList])
                                    if listStr not in dictDeleteRepeat:
                                        res.append(tempList)
                                        dictDeleteRepeat[listStr] = True
                            lastNumInner = nums[j]
                lastNum = nums[i]
        return res

无奈超时,后加以思索,优化第三数是否存在于数组之中的查询,遂AC。优化后如下:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        res = []
        dictDeleteRepeat = {}
        dictNums = {}
        for item in nums:
            dictNums[item] = True
        lastNum = None
        for i in range(len(nums)-2):
            if lastNum!=nums[i]:
                # 剪枝
                leftValue = 0-nums[i]
                lastNumInner = None
                if leftValue<=nums[-1]+nums[-2] and leftValue>=nums[i + 1]+nums[i + 2]:
                    for j in range(i+1,len(nums)-1):
                        if lastNumInner!=nums[j]:
                            # 再剪
                            leftValueInner = leftValue-nums[j]
                            if leftValueInner<=nums[-1] and leftValueInner>=nums[j + 1]:
                                if leftValueInner in dictNums:
                                    tempList = [nums[i],nums[j],leftValueInner]
                                    listStr = ''.join([str(item) for item in tempList])
                                    if listStr not in dictDeleteRepeat:
                                        res.append(tempList)
                                        dictDeleteRepeat[listStr] = True
                            lastNumInner = nums[j]
                lastNum = nums[i]
        return res

困难

#10 - 正则表达式匹配

题干

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 .*

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "a*"
输出: true
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

解题

很显然用回溯法,但为了干掉 s: aaaaaaaaaaaab,p: a*a*a*a*a*a*a*a*a*c 这种拦路虎,还需要多考虑许多。

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        return self.withRecalling(s,p)

    # sp means 'start point'
    def withRecalling(self,s,p,charLast='sp'):
        if len(s)>0:
            if len(p)>0:
                if p[-1]!='.' and p[-1]!='*' and p[-1]!=s[-1]:return False
            else:return False
            # certain character
            if s[0]==p[0]:
                resCertain = self.withRecalling(s[1:],p[1:],p[0])
                if resCertain:return True
            # dot
            if p[0]=='.':
                resDot = self.withRecalling(s[1:],p[1:],p[0])
                if resDot:return True
            # star
            if p[0]=='*':
                if charLast==s[0] or charLast=='.':
                    resStarRepeat = self.withRecalling(s[1:],p[0:],charLast)
                    if resStarRepeat:return True
                if len(p)>1:
                    resStar = self.withRecalling(s[:],p[1:],charLast)
                    if resStar:return True
            # lots of times or none
            if 1<len(p) and p[1]=='*':
                resLater = self.withRecalling(s[:],p[1:],p[0])
                if resLater:return True
        else:
            #
            if s==p:
                return True
            elif p[0]=='*':
                resLater = self.withRecalling(s[:],p[1:],p[0])
                if resLater:return True
            elif len(p)>1 and p[1]=='*':
                resLater = self.withRecalling(s[:],p[2:],p[0])
                if resLater:return True
            else:return False
        return False

后来看大佬们还有用动规的,有缘的话再折腾。

总结

未完待续

你可能感兴趣的:(算法,OJ)