leetcode专项刷题_动态规划(1)_判断子序列/打家劫舍/买卖股票的最佳时机

文章目录

  • 判断子序列
    • 题目描述
    • 代码实现
  • 打家劫舍
    • 题目描述
    • 代码实现
  • 买卖股票的最佳时机
    • 题目描述
    • 代码实现

判断子序列

题目描述

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)

# s = "abc", t = "ahbgdc"  >>>  True
# s = "axc", t = "ahbgdc"  >>>  False

代码实现

思路:

  1. 首先想到子字符串s的字母顺序是定死的,那么在t中找s, 其实就是按照s的字母顺序遍历就行了
  2. 按照s的字母顺序,每在t中找到一个,就让s的指针顺移一位,t的指针永远都要顺移一位
  3. 可能有人有疑问就是说s中有重复的子子串性的通吗?其实是一个道理,要理解第一条所说的的绝对顺序!
class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        count, s_index, t_index = 0, 0, 0
        while s_index < len(s) and t_index < len(t):
            if s[s_index] == t[t_index]:
                s_index += 1
                count += 1
            t_index += 1
        return count == len(s)

打家劫舍

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

代码实现

思路:

  1. 将问题使用归纳法从小到大进行分析,整理出头绪
  2. 看官方解答吧,很清晰— https://leetcode-cn.com/problems/house-robber/
# 动态规划
class Solution:
    
    def rob(self, nums):
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        dp = [0] * len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2, len(nums)):
            dp[i] = max(nums[i] + dp[i - 2], dp[i - 1])
        return dp[len(nums) - 1]

买卖股票的最佳时机

题目描述

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

示例 1:

  1. 输入: [7,1,5,3,6,4]
    输出: 5
    解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
    注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
    示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

代码实现

思路:

  1. 卖出股票的先决条件是存在一个值减去这个值索引前面位置的值大于0,不然就不卖,利润为0
  2. 所以就考虑找最小值以及当前位置减去最小值是否为利润最大值,并且保存此最大值,直至遍历结束
# 第一版本
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        if len(prices) == 1:
            return 0
        if len(prices) == 2 and prices[1] > prices[0]:
            return  prices[1] - prices[0] if prices[1] - prices[0] > 0 else 0
        # 主要是从这里开始的性能极其不好,但是易于理解,下一个版本就是优化这里
        dp = [0, prices[1] - prices[0] if prices[1] - prices[0] > 0 else 0]
        for i in range(2, len(prices)):
            dp.append(prices[i] - min(prices[:i]))
        return max(dp)
    
    
# 优化版本
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        if len(prices) == 1:
            return 0
        if len(prices) == 2 and prices[1] > prices[0]:
            return  prices[1] - prices[0] if prices[1] - prices[0] > 0 else 0
        min_num = prices[0]
        max_profit = 0
        for i in range(1, len(prices)):
            min_num = min(prices[i], min_num)
            max_profit = max(prices[i] - min_num, max_profit)
        return max_profit

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