• 【力扣hot100】刷题笔记Day25


    前言

    • 这几天搞工作处理数据真是类似我也,还被老板打电话push压力有点大的,还好搞的差不多了,明天再汇报,赶紧偷闲再刷几道题(可恶,被打破连更记录了)
    • 这几天刷的是动态规划,由于很成体系不适合零散刷,还是把代码随想录动态规划部分的题目快速再过一遍,代码简单但是思路也要记住

    139. 单词拆分 - 力扣(LeetCode)

    • 动态规划

        1. class Solution:
        2. def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        3. s_length = len(s)
        4. dp = [False] * (s_length + 1) # dp[i]表示s[0:i]能否被拼接
        5. dp[0] = True # 初始化,空字符串可以
        6. for i in range(1, s_length+1): # 遍历结束指针i
        7. for j in range(i): # 遍历开始指针j
        8. if dp[j] and s[j:i] in wordDict: # 如果j-1已经可拼,s[j:i]可再拼一个
        9. dp[i] = True # 整体就可以拼接
        10. break # 找到一组拼接,更新为True就退出
        11. return dp[s_length]

     300. 最长递增子序列 - 力扣(LeetCode)

    • 动态规划

        1. class Solution:
        2. def lengthOfLIS(self, nums: List[int]) -> int:
        3. n = len(nums) # dp[i]表示以nums[i]结尾的最长递增子串长度
        4. dp = [1] * n # 初始化为全1,子串至少为1个
        5. res = 1 # 结果先取1
        6. for i in range(1, n):
        7. for j in range(i):
        8. if nums[i] > nums[j]: # 只要比前面的递增,子串长度+1
        9. dp[i] = max(dp[i], dp[j] + 1)
        10. res = max(res, dp[i]) # 更新最长值
        11. return res

    152. 乘积最大子数组 - 力扣(LeetCode)

    • 动态规划

        1. class Solution:
        2. def maxProduct(self, nums: List[int]) -> int:
        3. n = len(nums)
        4. dp_max = [float('-inf')] * n # 表示以nums[i]为底的连续子数组的最大乘积,也可以用pre_max一个变量表示
        5. dp_min = [float('inf')] * n # 表示以nums[i]为底的连续子数组的最小乘积,也可以用pre_min一个变量表示
        6. dp_max[0] = dp_min[0] = res = nums[0]
        7. for i in range(1, n):
        8. # 由于当前可能正可能负,三种取最大/小:当前数,前最大×当前数,前最小×当前数
        9. dp_max[i] = max(nums[i], dp_max[i-1] * nums[i], dp_min[i-1] * nums[i])
        10. dp_min[i] = min(nums[i], dp_max[i-1] * nums[i], dp_min[i-1] * nums[i])
        11. res = max(res, dp_max[i])
        12. return res
    • 符号个数

      • 思路参考题解及评论区
        1. class Solution:
        2. def maxProduct(self, nums: List[int]) -> int:
        3. reverse_nums = nums[::-1]
        4. # 先按照0分成多个数组,在不同数组里统计奇数个数
        5. # 负数个数为偶数,全部相乘,负数个数为奇数,某奇数的前缀乘积或后缀乘积为最大值
        6. for i in range(1, len(nums)):
        7. nums[i] *= nums[i - 1] or 1 # 前缀乘积(遇到0就重置)
        8. reverse_nums[i] *= reverse_nums[i - 1] or 1 # 后缀乘积(遇到0就重置)
        9. return max(nums + reverse_nums) # 一定是前缀乘积和后缀乘积的最大值

    416. 分割等和子集 - 力扣(LeetCode)

    • 01背包

        1. class Solution:
        2. def canPartition(self, nums: List[int]) -> bool:
        3. numSum = sum(nums)
        4. if numSum % 2 == 1: return False # 总和为奇数无法等分
        5. target = numSum // 2 # 01背包大小
        6. dp = [0] * (target + 1) # dp[j]表示以j为容量的背包装的最大价值
        7. for i in range(len(nums)): # 遍历物品,从头到尾,重量和价值都为nums[i]
        8. for j in range(target, nums[i] - 1, -1): # 遍历背包,从target到nums[i]倒序
        9. dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
        10. return dp[target] == target # 如果target容量的背包刚好能装价值为target,找到分割方法

    32. 最长有效括号 - 力扣(LeetCode)

    • 辅助栈

      • 参考题解
        1. class Solution:
        2. def longestValidParentheses(self, s: str) -> int:
        3. st = [] # 栈中存储的是到当前位置暂时不可以构成括号的索引
        4. res = 0
        5. for i in range(len(s)):
        6. # 可以构成括号:栈不空 and 当前字符为'(' and 栈顶字符为'('
        7. if st and s[i] == ')' and s[st[-1]] == '(':
        8. st.pop() # 弹出栈顶'('
        9. # 与最远不能构成括号的下标计算距离,更新最大长度,注意越界
        10. res = max(res, i - (st[-1] if st else - 1))
        11. # 不可以构成括号:栈空 or 当前字符为')' or 栈顶字符为')'
        12. else:
        13. st.append(i) # 存入下标
        14. return res
    • 动态规划

      •  参考题解

        1. class Solution:
        2. def longestValidParentheses(self, s: str) -> int:
        3. n = len(s)
        4. if n <= 1: return 0
        5. dp = [0] * n # dp[i]表示以s[i]结尾的最长有效括号子串
        6. res = 0 # 用于更新最大值
        7. for i in range(1, n):
        8. # (),在dp[i-2]基础上直接延续2个
        9. if s[i] == ')' and s[i-1] == '(':
        10. dp[i] = dp[i-2] + 2 if i >= 2 else 2 # 防止越界,dp[0]以前为0
        11. # )),先看前一个)匹配多长,再看后一个)能否匹配上(,可以的话就+2
        12. elif s[i] == ')' and s[i-1] == ')':
        13. sub_len = dp[i-1] # 前一个)已经匹配的长度
        14. if i-sub_len-1 >= 0 and s[i-sub_len-1] == '(': # 后一个)要找到(才能匹配上
        15. last = dp[i-sub_len-2] if i-sub_len-2 >= 0 else 0 # 找到(之前已经匹配多长,防止越界,dp[0]以前为0
        16. dp[i] = dp[i-1] + last + 2 # 前一个)匹配的长度 + 后一个)找到(之前已经匹配的长度 + 2
        17. res = max(res, dp[i]) # 更新最大值,没有以上情况dp[i]就是0
        18. return res

    后言

    • 最后这道困难题真顶啊,要完全搞懂花了不少时间,这两天继续去巩固dp去
  • 相关阅读:
    ElasticSearch(一):介绍、安装、文档分词
    如何使用 Pyinstaller 编译打包 Python 项目生成 exe 可执行文件(2023 年最新详细教程)
    【torchvision】torchvision 介绍
    SCSS的嵌套规则可以减少重复代码,那么如何在嵌套规则中使用父选择器?
    Redis数据类型及命令
    springboot导入spring-boot-maven-plugin插件报错及打包项目到服务器上运行(手动导入加自动导入方法)-详细
    设计模式6大原则
    微信公众号记录
    fio的高级用法(锁定带宽,IOPS ,跳跃,混合,画图)
    Java基础之循环语句
  • 原文地址:https://blog.csdn.net/qq_56077562/article/details/136579304