[1日1つの質問] Li控除714。株式を売買するのに最適な時期には、手数料が含まれます。

タイトルの説明(ポータル

整数配列の価格が与えられた場合、i番目の要素はi日目の株価を表し、負でない整数の料金は株式の取引料金を表します。

取引は無期限に完了できますが、取引ごとに手数料を支払う必要があります。すでに株を購入している場合は、売却する前に株を購入することはできません。

得られた最大利益を返します。

注:ここでの取引とは、株式の売買の全過程を指し、取引ごとに手数料を支払うだけです。

输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
输出: 8
解释: 能够达到的最大利润:  
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.


アイデア

タイトルを見て最初に思ったのはDPでしたが、長い間試した結果、状態方程式が常に不適切だと感じ、公式回答を使って2DDPを使いました。
2次元配列dp [n] [2]を
定義します状態定義:

  • dp [i] [0]は、i日の終わりに手元に在庫がない場合の最大利益を表します。
  • dp [i] [1]は、i日の終わりに手元に在庫がある場合の最大利益を表します。

初期化:
dp [0] [0] = 0; //手元に在庫がありません
dp [0] [1] = 0-価格[0]; //手元に在庫があります。あなたがそれを買うならば、あなたはお金を使わなければなりません
。状態方程式:

dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] + prices[i] - fee);/// 第i天手中没有股票
dp[i][1] = Math.max(dp[i-1][0] - prices[i],dp[i-1][1]);//第i天手中有股票

最後の状態でi日に在庫がない状況は2つあります。

  1. i-1日目には在庫がないため、最大利益は前の状態の値のままです。
  2. i-1日目に株があり、同じ日に売られます。最大利益は、前の状態の利益に今日の株価を加えたものから販売コストを引いたものです。

i日目の在庫の最後の状態には2つの状況があります。

  1. i-1日目に在庫がない場合、最大利益は前の状態の値に今日の株価を加えたものになります。
  2. i-1日目に株があります。つまり、今日は株が売られておらず、最大利益はまだ最後の状態です。

コード:

 public static int maxProfit(int[] prices, int fee) {
    
    
        // 使用辅助数组dp【】 在这里每个元素都表示前i天的最大利润
        int[][] dp = new int[prices.length][2];
        dp[0][0] = 0;//手中没有股票
        dp[0][1] = 0 - prices[0];//手中有股票

        for (int i = 1; i < prices.length; i++) {
    
    

            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] + prices[i] - fee);/// 第i天手中没有股票
            dp[i][1] = Math.max(dp[i-1][0] - prices[i],dp[i-1][1]);

           //System.out.println(dp[i][0]);
        }
        return dp[prices.length-1][0];

    }

戻り値

dp [n-1] [0]が最大の利益を意味するのはなぜですか?
dp [i] [0]の結果を出力します:
ケース1:

// 输入:prices = [1, 3, 2, 8, 4, 9]
0
0
5
5
8

状況2:

// 输入:prices = [1, 3, 2, 8, 4, 4]
0
0
5
5
5

状態方程式から、dp [n-1] [0]が最大利益を更新することがわかります。2番目のケースの最終結果は5です。これは、5日目の価格が4のときに株式をまったく購入せず、6日目の価格が4のときに株式を購入しなかったことを意味します。彼の手には株がありません。

オンライン一次元最適化の結果を添付する

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


dp [i] dp [i]はdp [i-1] dp [i-1]からのみ転送できるため、最初の次元を削除できます。

おすすめ

転載: blog.csdn.net/weixin_45532227/article/details/111404205