2022-12-29 leetcode与蓝桥刷题情况

一、leetcode题目

1.买卖股票的最佳时机 III

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

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

2.测试用例

输入:

prices = [3,3,5,0,0,3,1,4]

输出:

6

解释:

在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

提示

  • 1 < = p r i c e s . l e n g t h < = 1 0 5 1 <= prices.length <= 10^5 1<=prices.length<=105
  • 0 < = p r i c e s [ i ] < = 1 0 5 0 <= prices[i] <= 10^5 0<=prices[i]<=105

3.思路

还是动态规划的树形dp,不过本题有较多限制,限制股票买卖次数,只能够买卖两次股票。这就需要有多种状态表示。

  • 状态表示:
  1. dp[i][0] 为不购买股票的最大价值。
  2. dp[i][1] 为第一次购买股票能够达到的最大价值。
  3. dp[i][2] 为第一次卖出股票能够达到的最大价值。
  4. dp[i][3] 为第二次买入股票能够达到的最大价值。
  5. dp[i][4] 为第二次卖出股票能够达到的最大价值。
  • 状态转移方程
  1. dp[i][0] = dp[i-1][0];
  2. dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]);
  3. dp[i][2] = max(dp[i-1][2], dp[i-1][1] - prices[i]);
  4. dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]);
  5. dp[i][4] = max(dp[i-1][4], dp[i-1][3] - prices[i]);]
  • 初始条件
    dp[0][1] = -prices[0], dp[0][3] = -prices[0];(因为同一天可以执行一次买入卖出操作,所以第一天的第二次买入的最大价值也为-prices[0]).

4.算法实现

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

因为dp[i]阶段的状态只依赖dp[i-1]阶段的状态,可只维护上个阶段的所有状态进行状态压缩。
下面是状态压缩代码的代码实现:

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

二、蓝桥题目

1.排列数

题目描述
在一个排列中,一个折点是指排列中的一个元素,它同时小于两边的元素,或者同时大于两边的元素。

对于一个 1 ~ n 1 ~ n 1n 的排列,如果可以将这个排列中包含 t t t 个折点,则它称为一个 t + 1 t + 1 t+1 单调序列。

例如,排列 (1,4,2,3) 是一个 3 单调序列,其中 42 都是折点。

给定 n n n k k k,请问 1   n 1 ~ n 1 n 的所有排列中有多少个 k k k 单调队列?
输入描述
输入一行包含两个整数 n , k   ( 1 ≤ k ≤ n ≤ 500 ) n, k\ (1 \leq k \leq n \leq 500) n,k (1kn500)

输出描述
输出一个整数,表示答案。答案可能很大,你可需要输出满足条件的排列数量除以 123456 的余数即可。

2.测试用例

输入:

4 2

输出:

12

3.思路

是动态规划,因为这一阶段的值可由上一阶段推导而来,但推导不出具体的状态转移方程式,就借鉴了一下题解。

4.算法实现

import java.util.Scanner;

public class main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int K = sc.nextInt();
        sc.close();
        int[][] dp = new int[N+1][K+1];
        dp[1][1]=1;
        dp[2][1]=2;
        for(int i=3;i<=N;i++){
            for(int j=1;j<=i&&j<=K;j++){
            dp[i][j] += dp[i - 1][j] * j;
            dp[i][j]%=123456;
            dp[i][j] += dp[i - 1][j - 1] * 2;
            dp[i][j]%=123456;
            if (j > 1){
                dp[i][j] += dp[i - 1][j - 2] * (i - j);
                dp[i][j]%=123456;
            }
            }
        }
        System.out.println(dp[N][K]);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值