代码随想录算法训练营第五十天|LeetCode309.买卖股票的最佳时机(含冷冻期)、LeetCode714.买卖股票的最佳时机(含手续费)

LeetCode 309 买卖股票的最佳时机(含冷冻期)

题目链接:309. 买卖股票的最佳时机含冷冻期 - 力扣(LeetCode)

【解题思路】

  • 1.确定dp数组含义

    • dp[i][j]

      • j的状态为

        • 持有股票状态

          • 状态一

            • 今天买入股票,或者是之前就买入了股票然后没有操作,一直持有股票

            • j=0

        • 不持有股票状态

          • 状态二

            • 保持卖出股票的状态

              • 两天前就卖出了股票,度过了一天冷冻期

              • 前一天就是卖出股票的状态,一直没操作

            • j=1

          • 状态三

            • 今天卖出股票

            • j=2

        • 冷冻期状态

          • 状态四

            • 今天为冷冻期,但冷冻期状态不可以持续,只有一天

            • j=3

  • 2.确定递推公式

    • 达到买入股票的状态

      • 状态一

        • dp[i][0]

          • 1.前一天就是持有股票的状态

            • dp[i][0]=dp[i-1][0]

          • 2.今天买入

            • 1)前一天是冷冻期

              • 状态四

                • dp[i-1][3]-prices[i]

            • 2)前一天是保持卖出股票的状态

              • 状态二

                • dp[i-1][1]-prices[i]

    • 达到保持卖出股票的状态

      • 状态二

        • dp[i][1]

          • 1.前一天就是状态二

            • dp[i-1][1]

          • 2.前一天是冷冻期

            • 状态四

              • dp[i-1][3]

    • 达到今天就卖出股票的状态

      • 状态三

        • dp[i][2]

          • 则昨天就一定是持有股票的状态

            • 状态一

              • 今天卖出

                • dp[i][2] = dp[i-1][0]+prices[i]

    • 达到冷冻期状态

      • 状态四

        • dp[i][3]

          • 昨天一定是卖出股票的状态(状态三)

            • dp[i][3] = dp[i-1][2]

  • 3.初始化dp数组

    • 持有股票的状态

      • 状态一

        • dp[0][0] = -prices[0]

          • 第一天就持有股票,那一定是当天买入股票

    • 保持卖出股票的状态

      • 状态二

        • dp[0][1] = 0

          • 根据递推公式的需要,我们只能初始化为0

    • 今天就卖出股票

      • 状态三

        • dp[0][2] = 0

          • 同上,根据公式的需要,只能初始化为0

  • 4.确定遍历顺序

    • 从递推公式可以看出dp[i]都是由dp[i-1]推导出来,所以一定是从前向后遍历

  • 5.举例推导dp数组

【解题步骤】

  • 1.如果prices的长度为0,直接返回0

  • 2.创建一个长度为prices.length和4的数组

  • 3.初始化dp[0][0]

  • 4.遍历数组

    • 递推公式

  • 5.返回状态二,状态三,状态四的最大值

【代码部分】

class Solution {
    public int maxProfit(int[] prices) {
		int len = prices.length;
		if(len == 0)return 0;
		int[][] dp = new int[len][4];
		dp[0][0] = -prices[0];
		for (int i = 1; i < len ; i++) {
			dp[i][0] = Math.max(dp[i-1][0],Math.max(dp[i-1][3]-prices[i],dp[i-1][1]-prices[i]));
			dp[i][1] = Math.max(dp[i-1][1],dp[i-1][3]);
			dp[i][2] = dp[i-1][0]+prices[i];
			dp[i][3] = dp[i-1][2];
		}
		return Math.max(dp[len-1][3],Math.max(dp[len-1][1],dp[len-1][2]));
    }
}

LeetCode 714 买卖股票的最佳时机(含手续费)

题目链接:714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)

【解题思路】

  • 1.确定dp数组含义

    • dp[i][0]表示第i天持有股票所得到的最大现金

    • dp[i][1]表示第i天不持有股票所得到的最大现金

    • 求的结果是dp[len-1][0]和dp[len-1][1]中的最大值

  • 2.确定递推公式

    • 第i天持有股票

      • dp[i][0] = max(dp[i-1][0],dp[i-1][1]-price[i])

        • 第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]

        • 第i天买入股票,所得现金就是买入今天的股票后所得现金即:dp[i-1][1]-prices[i]

          • 跟上一题唯一的区别就是可以买入多次,所以是前一天没有股票的现金减去买股票花的钱

    • 第i天不持有股票

      • dp[i][1] = max(dp[i-1][1],price[i]+dp[i-1][0]-fee)

        • 第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]

        • 第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]

          • 注意要减去手续费fee

  • 3.初始化dp数组

    • dp[0][0]= -price[0]

      • 表示第一天买入股票(持有股票)

    • dp[0][1] = 0

      • 表示第一天不买入股票(不持有股票)

  • 4.确定遍历顺序

    • 从递推公式可以看出dp[i]都是由dp[i-1]推导出来,所以一定是从前向后遍历

  • 5.举例推导dp数组

【解题步骤】

  • 1.如果prices为空或者prices长度为0,直接返回0

  • 2.新建一个二维dp数组,长度为price的长度和2

  • 3.初始化dp[0][0]=-prices[0];dp[0][1]=0

  • 4.从前往后遍历数组

    • 递推公式

  • 5.返回dp[length-1][1]

【代码部分】

class Solution {
    public int maxProfit(int[] prices, int fee) {
		if(prices == null || prices.length == 0)return 0;
		int [][] dp = new int[prices.length][2];
		dp[0][0]=-prices[0];
		dp[0][1]=0;
		for(int i = 1 ;  i < dp.length ; i++){
			dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
			dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i] - fee);
		}
		return dp[prices.length - 1][1];
    }
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值