NC+LC:买卖股票的最好时机
1、股票(一次交易)
LC 121.买卖股票的最好时机:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/
题目描述
假设你有一个数组,其中第
个元素是股票在第
天的价格。
你有一次买入和卖出的机会。(只有买入了股票以后才能卖出)。请你设计一个算法来计算可以获得的最大收益。
你有一次买入和卖出的机会。(只有买入了股票以后才能卖出)。请你设计一个算法来计算可以获得的最大收益。
示例
输入:[7,1,5,3,6,4] 输出:5 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
解法一:暴力解法
思路
从第一个元素开始往后遍历,与它后面的元素进行比较,遇到比它大的元素就求其差值,通过比较求出最大的差值,这种做法的时间复杂度为)
实现代码
import java.util.*;
public class Solution {
public int maxProfit (int[] prices) {
// write code here
if(prices == null || prices.length == 0) {
return 0;
}
int max = 0;
for(int i = 0; i<prices.length-1; i++){
for(int j = i+1; j<prices.length; j++){
if(prices[j] > prices[i]){
int tmp = prices[j] - prices[i];
if(max < tmp){
max = tmp;
}
}
}
}
return max;
}
} 解法二:贪心算法
思路
- 这题实际上是在求
- 利用贪心算法的思路(不考虑全局,从头开始求局部最优解,保持在这个局部范围内的最小买入值)维护
在
范围内最小
- 保持当前的最小买入值,将往后的值进行相减求差值,再通过比较获得局部的最大收益值并将其保持,以此类推不断逼近得到最大的差值
- 此解法时间复杂度为
实现代码
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0) return 0;
int buy = prices[0];
int max = 0;
for(int i = 1; i < prices.length; i++){
buy = Math.min(buy, prices[i]); //记录当前的最小买入值
max = Math.max(max, prices[i] - buy); //求当前局部的最大收益值
}
return max; //最终得到全局的最大收益值
}
} 2、股票(两次交易)
LC 123.买卖股票的最佳时机 III:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/
题目描述
假定你知道某只股票每一天价格的变动。
你最多可以同时持有一只股票。但你最多只能进行两次交易(一次买进和一次卖出记为一次交易。买进和卖出均无手续费)。
请设计一个函数,计算你所能获得的最大收益。 解法一
思路
以当前位置作为第二次交易的买入点,保持当前价格与第一次收益的最小差值作为第二次买入的价格
实现代码
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 两次交易所能获得的最大收益
* @param prices int整型一维数组 股票每一天的价格
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
int fstBuy = Integer.MAX_VALUE;
int fstSell = 0;
int secBuy = Integer.MAX_VALUE;
int secSell = 0;
for(int price : prices){
//第一次交易
fstBuy = Math.min(fstBuy, price);
fstSell = Math.max(fstSell, price-fstBuy);
//以当前位置作为第二次交易的买入点,保持当前价格与第一次收益的最小差值作为第二次买入的价格
secBuy = Math.min(secBuy, price-fstSell);
secSell = Math.max(secSell, price-secBuy);
}
return secSell;
}
} 解法二
思路
- 可以先从后往前遍历,求出从当前点到之后的一次交易的最大收益值,将其记录在一个数组中
- 再从前往后进行遍历,按照一次交易的贪心算法思路,求出第一次交易的收益值加上当前位置往后的第二次收益值,通过比较求出其中的最大值
实现代码
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 两次交易所能获得的最大收益
* @param prices int整型一维数组 股票每一天的价格
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
int n = prices.length;
if(n<2) return 0;
//从后往前遍历,f[i]记录了从i点到之后的一次交易的最大收益
int[] f = new int[n];
int max = prices[n-1];
f[n-1] = 0; //初始化
for(int i = n-2; i>=0; i--){
max = Math.max(max, prices[i]);//记录当前的最大卖出点
f[i] = Math.max(f[i+1], max-prices[i]);
}
int res = 0;
//从前往后遍历
int min = Integer.MAX_VALUE;
for(int i = 0; i<n-1; i++){
min = Math.min(min, prices[i]);
//每次在第一次交易的收益上加上当前位置之后对应的f[i+1],通过比较求最大值
res = Math.max(res, prices[i] - min + f[i+1]);
}
return res;
}
} 3、股票(多次交易)
LC 122.买卖股票的最好时机 II:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
题目描述
给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
解法一:贪心算法
思路
- 因为可以进行多次交易,那么要想获得最大收益,就需要将每一个上升的区间的收益进行相加
- 只需从头开始遍历,将前后两数之间的差值计算出来,大于0的就说明有收益,将收益值进行累加
实现代码
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0) return 0;
int sumValue = 0;
for(int i = 0; i < prices.length - 1; i++){
//遍历数组,将后一个数减去前一个数,大于0就说明有收益,进行累加
int dif = prices[i + 1] - prices[i];
if(dif > 0){
sumValue += dif;
}
}
return sumValue;
}
} 
