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; } }