算法(买卖股票的的最佳时机)

1.题目描述

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多只能持有一股 股票。你也可以先购买,然后在 同一天出售。返回你能获得的最大利润 。

示例1

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 (股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。 总利润为 4 + 3 = 7 。

示例2

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。总利润为 4 。

示例3

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

提示:

  • 1 <= prices.length <= 3 * 104
  • 0 <= prices[i] <= 104

解法一(动态规划):

分析:当日利润最大分为两种情况:(1)手中没有股票(2)手中有股票

当为情况(1)的时候,则可能是当日没有买入股票,利润是前一天卖掉股票的利润,也可能是当日把前一天的股票卖掉了的利润

当为情况(2)的时候,则可能是当日没有买入股票,利润是前一天买入股票的利润,也可能是当日买了如票的利润

根据分析就可以设置两个变量:nohold和hold,每一次更新一次当日的nohold和hold的最大利润

推导公式:nohold=max(hold+prices[i],nohold)

                  hold=max(hold,nohold-prices[i])

package LeetCode;
class Solution {
    public int maxProfit(int[] prices) {
        if(prices==null||prices.length==0){
            return 0;
        }
        int hold=-prices[0];
        int nohold=0;
        for(int i=1;i<prices.length;i++){
            hold=max(hold,nohold-prices[i]);
            nohold=max(nohold,hold+prices[i]);
        }
        return nohold;
    }
    public int max(int a,int b){
        if(a>b){
            return a;
        }else if(a==b){
            return a;
        }else{
            return b;
        }
    }
}
public class 买卖股票最佳时机 {
    public static void main(String[] args) {
        int[]A={1,5,4,9,2,3};
        Solution solution=new Solution();
        System.out.println(solution.maxProfit(A));
    }
}

解法二(贪心算法)

分析:根据观察每日股票的市值图,图像有增有减,又图像可以得出,最大利润就是所股票市值上升的差值之和。

首先,定义一个索引index,先判断当股票下降的情况,股票下降的话index就一直增,当下降到谷底的时候记录prices[index]的值,再判断增长的情况,index一直增长直到找到波峰,此时定义一个变量total来记录增长段的每次的差值之和(即最大利润),最后还有一层外层循环来让指针index不断的遍历整个数组从而实现代码。

package LeetCode;
class Sol {
    public int MaxProfit(int[] prices){
        if (prices == null||prices.length<2) {
            return 0;
        }
        int index=0,total=0;
        while(index<prices.length){
            while(index<prices.length-1&&prices[index]>=prices[index+1]){
                index++;
            }
            int min=prices[index];
            while(index<prices.length-1&&prices[index]<=prices[index+1]){
                index++;
            }
            total+=prices[index++]-min;//这里的index只能用index++,不然index就无法走到数组的长度+1,从而就无法推出循环
        }
        return total;
    }
}
    public class 买卖股票最佳时机2 {

        public static void main(String[] args) {
            int[]B={1,5,4,9,2,3};
            Sol sol=new Sol();
            System.out.println(sol.MaxProfit(B));

        }
}

解法三(贪心算法的优化)

分析:在贪心算法的基础上,定义一个变量ans,ans不断的累加上0和第二天和第一天的股票市值差值的最大值(即当第二天高于第一天就加上差值,若第二天小于第一天就加上0),这样下来就只用一个变量就可以不断地类加上增长的每一段,从而计算出最大利润。

package LeetCode;
class FastSolution{
    public int max(int []price){
        //判断数字是否为零或者未1而不符合题目要求
        if(price==null||price.length<2){
            return 0;
        }
        int ans=0;
        for (int i = 1; i <price.length ; i++) {
            ans+=Math.max(0,price[i]-price[i-1]);
        }
        return ans;
    }
}
public class 买卖股票最佳时机3 {
    public static void main(String[] args) {
        FastSolution fastSolution=new FastSolution();
        int []M={1,5,4,9,2,3};
        System.out.println(fastSolution.max(M));
    }

}

注意:在代码实现的时候一定要注意边界问题,否则可能在循环的时候一直跳不出循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值