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));
}
}
注意:在代码实现的时候一定要注意边界问题,否则可能在循环的时候一直跳不出循环。