代码随想录-Day50-补动态规划-买卖股票-309. 买卖股票的最佳时机含冷冻期||714. 买卖股票的最佳时机含手续费||子序列问题-300. 最长递增子序列||674. 最长连续递增序列

309. 买卖股票的最佳时机含冷冻期

给定一个整数数组prices,其中第  prices[i] 表示第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

集体思路:最主要的就是确定每一个状态,便于推导出状态转移方程

具体完整思路详见注释:

class Solution {
    public int maxProfit(int[] prices) {
        //动态规划解决
        //1,dp数组含义,
        //dp[i][j] 第i天的状态为j,所剩余的最多现金为dp[i][j]
        //具体状态分析
        //dp[0][0]:买入股票的状态,有可能是当天买入,也有可能是买入之后没有卖出
        //dp[0][1]:保持卖出股票的状态,就是已经度过了冷冻期,但是没有操作
        //dp[0][2]:卖出股票的转态,指的就是当天卖出了股票
        //dp[0][3]:今天是冷冻期
        int len=prices.length;
        if(len==0) return 0;
        int[][] dp=new int[len+1][4];
        //初始化dp数组,
        //根据含义初始化
        dp[0][0]=-prices[0];
        //其余按照状态初始化为0根据状态转移方程解决
        //遍历
        for(int i=1;i<len;i++){
            //推导每一步的状态转移方程
            //1,买入股票可以根据两个状态推导,一个是前一天就是买入的状态
            //另一个就是前一天不是买入的状态,那么就有可能是
            //前一天是卖出的状态,或者前一天是冷冻期
            dp[i][0]=Math.max(dp[i-1][0],
                     Math.max(dp[i-1][3],dp[i-1][1])-prices[i]);
            //2,保持卖出股票的状态,一种是前一天就是这种状态,
            //另一种是前一天是冷冻期
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][3]);
            //3,当天卖出股票的状态只能是前一天卖出股票
            dp[i][2]=dp[i-1][0]+prices[i];
            //4,今天是冷冻期,前一天一定是卖出股票的状态
            dp[i][3]=dp[i-1][2];
        }
        //最后结余的最大值一定是在1,2,3状态中诞生,因为买入但不卖出很亏
        return Math.max(dp[len-1][1],
                        Math.max(dp[len-1][2],
                        dp[len-1][3]));

    }
}

714. 买卖股票的最佳时机含手续费

给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

解题思路:相对来说还是比较简单的,使用两种状态就可以解决,一种是买入,一种是卖出,只不过在卖出的时候加上一个手续费用即可,状态转移方程还是根据买与不买的两种状态进行推导,求解出最大值。

具体代码:

class Solution {
    public int maxProfit(int[] prices, int fee) {
        //动态规划
        //1,dp数组含义
        //dp[i][0]第i天交易完成之后手中没有股票的最大利润
        //dp[i][1]第i天交易完成之后手中有股票的最大利润
        int len=prices.length;
        int[][] dp=new int[len][2];
        //2,确定递推公式
        //就是保持前一天的状态不变和改变状态买入或者卖出的最大值
        //dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-free)
        //dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
        //3,初始化
        dp[0][0]=0;
        dp[0][1]=-prices[0];
        //4,循环遍历
        for(int i=1;i<len;i++){
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
        }
        return Math.max(dp[len-1][0],dp[len-1][1]);
    }
}

300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

解题思路:可以理解大致的递推公式思路,但是代码实现之后并不是很能理解,之后再看

class Solution {
    public int lengthOfLIS(int[] nums) {
        //动态规划中的子序列问题
        //使用动规五部曲来分析,重点明白dp数组的含义
        //1,dp数组含义
        //dp[i] 表示以数组下表i之前,以nums[i]结尾的最长递增子序列的长度\
        int len=nums.length;
        int[] dp=new int[len];
        Arrays.fill(dp,1);
        int result=0;
        //2,确定递推公式
        //如果后续元素大于上一个元素,才进行增加
        //dp[i]=max(dp[j],dp[j]+1)
        //3,dp数组初始化
        //根据dp数组含义,每一个do数组值的初始化长度都应该为1
        for(int i=0;i<len;i++){
            for(int j=0;j<i;j++){
                if(nums[i]>nums[j]){
                    dp[i]=Math.max(dp[i],dp[j]+1);
                }
            }
            if(dp[i]>result) result=dp[i];
        }
        return result;
    }
}

674. 最长连续递增序列

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 rl < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

解题思路:这个就比较简单了,直接秒了,附上代码吧,代码里面甚至都没有注释

class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int res=1;
        int max=1;
        for(int i=1;i<nums.length;i++){
            if(nums[i]>nums[i-1]){
                max++;
            }else{
                max=1;
            }
            res=Math.max(max,res);
        }
        return res;
    }
}

剩余的继续补,没办法,谁让我玩嗨了捏!!

                                                                                                                                By-三条直线围墙

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值