买卖股票的最好时机

买卖股票

解题思路:利用两个遍历,一个是min另外一个是profit

import java.util.*;


public class Solution {
    /**
     * 
     * @param prices int整型一维数组 
     * @return int整型
     */
    public int maxProfit (int[] prices) {
        // write code here
        if(prices == null || prices.length == 0){
            return 0;
        }
        int min = prices[0];
        int profit = 0;
        for(int i =  1; i < prices.length; i++){
            min = Math.min(min, prices[i-1]);
            profit = Math.max(profit, prices[i] - min);
        }
        return profit;
    }
}

买卖股票(无限次交易)

1. 利用动态规划

dp[i][0]表示如果这一天交易完后手里没有股票,那么状态转移dp[i][0]=max(dp[i-1][0], dp[i-1][1] + price[i])

  • 前一天没有股票,今日也未买入, 则dp[i][0]=dp[i-1][0]
  • 前一天有股票,今日卖出, 则dp[i][0]=dp[i-1][1] + price[i]

dp[i][1]表示如果这一天交易完后手里有股票, dp[i][1]=max(dp[i-1][0] - price[i], dp[i-1][1])

  • 前一天没有股票, 今日买入,则dp[i][1]=dp[i-1][0] - price[i]
  • 前一天就持有股票,今日不卖出,则dp[i][1]=dp[i-1][1]

对于初始状态,也dp[n-1][0]就是第0天交易结束的时候: dp[0][0] = 0, dp[0][1] = -price[0], 只要从前往后依次计算状态即可。当全部交易结束后, 持有股票的收益一定低于持有股票的收益,也就是dp[n-1][0] > dp[n-1][1]。 最后答案为dp[n-1][0]

实现代码

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 计算最大收益
     * @param prices int整型一维数组 股票每一天的价格
     * @return int整型
     */
    public int maxProfit (int[] prices) {
        // write code here
        int len = prices.length;
        int[][] dp = new int[len][2];
        dp[0][0]= 0;
        dp[0][1] = -prices[0];
        for(int i = 1; i < len; i++){
            dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = Math.max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
        }
        return dp[len-1][0];
    }
}

优化空间至O(1)

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 计算最大收益
     * @param prices int整型一维数组 股票每一天的价格
     * @return int整型
     */
    public int maxProfit (int[] prices) {
        // write code here
        int len = prices.length;
        int dp0 = 0;
        int dp1 = -prices[0];
        for(int i = 1; i < len; i++){
            int newdp0 = Math.max(dp0, dp1 + prices[i]);
            int newdp1 = Math.max(dp0 - prices[i], dp1);
            dp0 = newdp0;
            dp1 = newdp1;
        }
        return dp0;
    }
}

2. 贪心法

因为购买股票没有限制,整个问题等价于寻找x个不相交的区间(l_i,r_i], 最大化\sum_{i=1}^{x}a[r_i]-a[l_i]

l_i表示在第l_i天买入, r_i表示在第r_i天卖出。值得注意的是:区间 (l_i,r_i]贡献的价值a[r_i]-a[l_i] = (a[r_i]-a[r_i-1]) +(a[r_i -1]-a[r_i-2]) +...+(a[l_i + 1]-a[l_i] )

因此问题就简化成了,找n个长度为1的区间(l_i, l_i+1]使得\sum_{i=1}^{n-1}a[l_i+1]-a[l_i]值最大。

从贪心的角度只要每次选择贡献大于0的区间即可以最大化, 最后答案为

ans = \sum_{i=1}^{n-1}max(0, a[i]-a[i-1])

但是,贪心算法只能用于计算最大化利润,计算的过程并不是实际的交易过程。

实现代码

    public int maxProfit (int[] prices) {
        // write code here
        int len = prices.length;
        int ans = 0;
        for(int i = 1; i < len; i++){
            ans += Math.max(0, prices[i] - prices[i-1]);
        }
        return ans;
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值