leecode更新
This commit is contained in:
parent
947ed0fbf5
commit
607b5f6af2
|
|
@ -0,0 +1,104 @@
|
|||
package com.markilue.leecode.dynamic.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||
*@Author: markilue
|
||||
*@CreateTime: 2023-02-21 09:50
|
||||
*@Description:
|
||||
* TODO 力扣121 买卖股票的最佳时机:
|
||||
* 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
|
||||
* 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
|
||||
* 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T21_MaxProfit {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int[] prices = {7, 1, 5, 3, 6, 4};
|
||||
System.out.println(maxProfit2(prices));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 思路:事实上思路是一致的:将当前收益分为手上有股票和手上没有股票 注意只能买卖一次
|
||||
* TODO DP五部曲:
|
||||
* 1.dp定义: dp[i][0]表示第i天手上没有股票的最大收益;dp[i][1]表示第i天手上有股票的最大收益
|
||||
* 2.dp状态转移方程:
|
||||
* 1.dp[i][0] 昨天没有今天没买 ; 昨天有今天卖了
|
||||
* dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i])
|
||||
* 2.dp[i][1] 昨天有今天没卖 ; 昨天没有今天买了
|
||||
* dp[i][1]=max(dp[i-1][1],-prices[i])
|
||||
* 3.dp初始化:dp[0][0]=0; dp[0][1]=-price[0];
|
||||
* 4.dp遍历顺序:从前往后
|
||||
* 5.dp举例推导:
|
||||
* 速度击败5.69% 内存击败89.6%
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit(int[] prices) {
|
||||
|
||||
int[][] dp = new int[prices.length][2];
|
||||
dp[0][0] = 0;
|
||||
dp[0][1] = -prices[0];
|
||||
|
||||
for (int i = 1; i < dp.length; i++) {
|
||||
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
|
||||
dp[i][1] = Math.max(dp[i - 1][1], -prices[i]);
|
||||
}
|
||||
|
||||
return dp[dp.length - 1][0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一维dp优化
|
||||
* 速度击败54.5% 内存击败66.9%
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit1(int[] prices) {
|
||||
|
||||
int dp0 = 0;
|
||||
int dp1 = -prices[0];
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
dp0 = Math.max(dp0, dp1 + prices[i]);
|
||||
dp1 = Math.max(dp1, -prices[i]);
|
||||
}
|
||||
|
||||
return dp0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 贪心算法
|
||||
* 速度击败100% 内存击败42.58%
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit2(int[] prices) {
|
||||
|
||||
int minPrice = prices[0];
|
||||
int maxProfit = 0;
|
||||
int curProfit = 0;
|
||||
|
||||
//只买卖一次
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
if (minPrice > prices[i]) {
|
||||
minPrice = prices[i];
|
||||
continue;
|
||||
}
|
||||
curProfit = prices[i] - minPrice;
|
||||
if (maxProfit < curProfit) maxProfit = curProfit;
|
||||
}
|
||||
|
||||
return maxProfit;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package com.markilue.leecode.dynamic.second;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||
*@Author: markilue
|
||||
*@CreateTime: 2023-02-21 10:39
|
||||
*@Description:
|
||||
* TODO 力扣122 买卖股票的最佳时机II:
|
||||
* 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
|
||||
* 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
|
||||
* 返回 你能获得的 最大 利润 。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T22_MaxProfit {
|
||||
|
||||
/**
|
||||
* 与上一题不同之处在于:收益可以累加
|
||||
* 所以 dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0]-prices[i]);
|
||||
* 速度击败25.56% 内存击败9.38% 3ms
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit(int[] prices) {
|
||||
int[][] dp = new int[prices.length][2];
|
||||
dp[0][0] = 0;
|
||||
dp[0][1] = -prices[0];
|
||||
|
||||
for (int i = 1; i < dp.length; i++) {
|
||||
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
|
||||
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
|
||||
}
|
||||
|
||||
return dp[dp.length - 1][0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一维dp优化
|
||||
* 速度击败83.44% 内存击败49.3% 1ms
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit1(int[] prices) {
|
||||
|
||||
int dp0 = 0;
|
||||
int dp1 = -prices[0];
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
dp0 = Math.max(dp0, dp1 + prices[i]);
|
||||
dp1 = Math.max(dp1, dp0 - prices[i]);
|
||||
}
|
||||
|
||||
return dp0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 贪心
|
||||
* 速度击败83.44% 内存击败81.45% 1ms
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit2(int[] prices) {
|
||||
|
||||
int profit = 0;
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
int curDiff = prices[i] - prices[i - 1];
|
||||
if (curDiff > 0) profit += curDiff;//因为可以当天买当天卖
|
||||
}
|
||||
|
||||
return profit;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package com.markilue.leecode.dynamic.second;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||
*@Author: markilue
|
||||
*@CreateTime: 2023-02-21 10:48
|
||||
*@Description:
|
||||
* TODO 力扣123 买卖股票的最佳时机III:
|
||||
* 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
|
||||
* 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
|
||||
* 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T23_MaxProfit {
|
||||
|
||||
|
||||
/**
|
||||
* 思路:不同之处在于规定了最多只能完成两笔交易 所以将状态定为五种
|
||||
* TODO DP五部曲:
|
||||
* 1.dp定义:dp[i][0],dp[i][1],dp[i][2],dp[i][3]分别代表 第i天 第一次买入 第一次卖出 第二次买入 第二次卖出
|
||||
* 2.dp状态转移方程:
|
||||
* 1.dp[i][0] 由于是第一次买入,所以之前是没有收益的
|
||||
* dp[i][0]=max(dp[i-1][0],-prices[i])
|
||||
* 2.dp[i][1] 由于是第一次卖出
|
||||
* dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i])
|
||||
* 3.dp[i][2] 由于是第二次买入
|
||||
* dp[i][2]=max(dp[i-1][2],dp[i-1][1]-prices[i])
|
||||
* 4.dp[i][3] 由于是第一次卖出
|
||||
* dp[i][3]=max(dp[i-1][3],dp[i-1][2]+prices[i])
|
||||
* 3.dp初始化:dp[i][0]=-price[0],dp[i][1]=0,dp[i][2]=-price[0],dp[i][3]=0
|
||||
* 4.dp遍历顺序:
|
||||
* 5.dp举例推导: 以prices = [3,3,5,0,0,3,1,4]为例
|
||||
* [0 1 2 3]
|
||||
* 3: -3 0 -3 0
|
||||
* 3: -3 0 -3 0
|
||||
* 5: -3 2 -3 2
|
||||
* 0: 0 2 2 2
|
||||
* 0: 0 2 2 2
|
||||
* 3: 0 3 2 5
|
||||
* 1: 0 3 2 5
|
||||
* 4: 0 4 2 6
|
||||
* 速度击败23.76% 内存击败80.68% 35ms
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit(int[] prices) {
|
||||
|
||||
int[][] dp = new int[prices.length][4];
|
||||
dp[0][0] = -prices[0];
|
||||
dp[0][1] = 0;
|
||||
dp[0][2] = -prices[0];
|
||||
dp[0][3] = 0;
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
dp[i][0]=Math.max(dp[i-1][0],-prices[i]);
|
||||
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
|
||||
dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]-prices[i]);
|
||||
dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]+prices[i]);
|
||||
}
|
||||
|
||||
|
||||
return dp[dp.length-1][3];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 滚动数组优化
|
||||
* 速度击败87.55% 内存击败42.27% 2ms
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit1(int[] prices) {
|
||||
|
||||
|
||||
int dp0 = -prices[0];
|
||||
int dp1 = 0;
|
||||
int dp2 = -prices[0];
|
||||
int dp3 = 0;
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
dp0=Math.max(dp0,-prices[i]);
|
||||
dp1=Math.max(dp1,dp0+prices[i]);
|
||||
dp2=Math.max(dp2,dp1-prices[i]);
|
||||
dp3=Math.max(dp3,dp2+prices[i]);
|
||||
}
|
||||
|
||||
|
||||
return dp3;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快:贪心? 本质上跟上面一样还是动态规划,只是将dp[0]的推导变成了贪心的模式
|
||||
* 速度击败100% 内存击败30.8% 1ms
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit2(int[] prices) {
|
||||
int min=prices[0];//第一次买入的最小价格
|
||||
int p1=0;//第一次卖出的收益
|
||||
|
||||
int max1=Integer.MIN_VALUE;//第二次买入的最大收益
|
||||
int p2=0; //第二次卖出的收益
|
||||
|
||||
for(int i=1;i<prices.length;++i){
|
||||
if(prices[i]>min)
|
||||
p1=Math.max(p1,prices[i]-min);
|
||||
else if(prices[i]<min)
|
||||
min=prices[i];
|
||||
p2= Math.max(p2,prices[i]+max1);
|
||||
max1=Math.max(max1,p1-prices[i]);
|
||||
|
||||
}
|
||||
return Math.max(p1,p2);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.markilue.leecode.dynamic.second;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||
*@Author: markilue
|
||||
*@CreateTime: 2023-02-21 11:20
|
||||
*@Description:
|
||||
* TODO 力扣188 买卖股票的最佳时机IV:
|
||||
* 给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。
|
||||
* 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
|
||||
* 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T24_MaxProfit {
|
||||
|
||||
/**
|
||||
* 思路:将上一题的最多2次变成了最多k次,可以根据上一题的思路进行状态转移方程的演变
|
||||
* 1.dp[i][j%2==0] 由于是第一次买入,所以之前是没有收益的
|
||||
* dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]-prices[i])
|
||||
* 2.dp[i][j%2==1] 由于是第一次卖出
|
||||
* dp[i][1]=max(dp[i-1][j],dp[i-1][j-1]+prices[i])
|
||||
* 速度击败59.98% 内存击败70.44%
|
||||
* @param k
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit(int k, int[] prices) {
|
||||
|
||||
int[][] dp = new int[prices.length][2 * k];
|
||||
for (int i = 0; i < dp[0].length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
dp[0][i] = -prices[0];
|
||||
} else {
|
||||
dp[0][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
dp[i][0] = Math.max(dp[i - 1][0], -prices[i]);
|
||||
for (int j = 1; j < dp[0].length; j++) {
|
||||
if (j % 2 == 1) {
|
||||
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - 1] + prices[i]);
|
||||
} else {
|
||||
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dp[prices.length-1][2*k-1];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一维dp优化:
|
||||
* 速度击败99.81% 内存击败93.44%
|
||||
* @param k
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit1(int k, int[] prices) {
|
||||
|
||||
int[] dp = new int[2 * k];
|
||||
for (int i = 0; i < dp.length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
dp[i] = -prices[0];
|
||||
} else {
|
||||
dp[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
dp[0] = Math.max(dp[0], -prices[i]);
|
||||
for (int j = 1; j < dp.length; j++) {
|
||||
if (j % 2 == 1) {
|
||||
dp[j] = Math.max(dp[j], dp[j - 1] + prices[i]);
|
||||
} else {
|
||||
dp[j] = Math.max(dp[j], dp[j - 1] - prices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dp[2*k-1];
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package com.markilue.leecode.dynamic.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.dynamic.second
|
||||
*@Author: markilue
|
||||
*@CreateTime: 2023-02-21 11:54
|
||||
*@Description:
|
||||
* TODO 力扣309题 最佳买卖股票时机含冷冻期:
|
||||
* 给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。
|
||||
* 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
|
||||
* 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
|
||||
* 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T25_MaxProfit {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
int[] dp={1,2,3,0,2};
|
||||
System.out.println(maxProfit(dp));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 思路:不同之处在于 含冷冻期了 分为三种状态 手上有股票 手上没股票 处于冷冻期
|
||||
* TODO dp五部曲:
|
||||
* 1.dp定义: dp[i][0] dp[i][1] dp[i][2] 分别表示手上有股票 手上没股票(可操作) 手上没有股票(不可操作) 三种情况
|
||||
* 2.dp状态转移方程:
|
||||
* 1.dp[i][0] 手上没有股票可操作 ;昨天就可以操作 ;昨天不可操作今天可操作性 ;
|
||||
* dp[i][0]=max(dp[i-1][0],dp[i-1][1])
|
||||
* 2.dp[i][1] 手上没有股票(不可操作) :昨天有今天卖了 今天处于冷冻期 不可操作
|
||||
* dp[i][1]=max(dp[i-1][1],dp[i-1][2]+prices[i])
|
||||
* 3.dp[i][2] 手上有股票:昨天不可操作今天买了 昨天可操作今天买了 昨天有今天有
|
||||
* dp[i][2]=max(dp[i-1][2],dp[i-1][1]-prices[i],dp[i-1][0]-prices[i])
|
||||
*
|
||||
* 3.dp初始化:dp[0][0]=0;dp[0][1]=0;dp[0][2]=-prices[0]
|
||||
* 4.dp遍历顺序:
|
||||
* 5.dp举例推导:
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit(int[] prices) {
|
||||
|
||||
int[][] dp = new int[prices.length][3];
|
||||
dp[0][0] = 0;
|
||||
dp[0][1] = 0;
|
||||
dp[0][2] = -prices[0];
|
||||
|
||||
for (int i = 1; i < dp.length; i++) {
|
||||
dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]);
|
||||
dp[i][1]=Math.max(dp[i-1][1],dp[i-1][2]+prices[i]);
|
||||
dp[i][2]=Math.max(dp[i-1][2],dp[i-1][0]-prices[i]);
|
||||
}
|
||||
|
||||
return Math.max(dp[dp.length-1][0],dp[dp.length-1][1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 一维dp优化
|
||||
* @param prices
|
||||
* @return
|
||||
*/
|
||||
public int maxProfit1(int[] prices) {
|
||||
|
||||
|
||||
int dp0 = 0;
|
||||
int dp1 = 0;
|
||||
int dp2 = -prices[0];
|
||||
int temp0=0;
|
||||
|
||||
for (int i = 1; i < prices.length; i++) {
|
||||
temp0=dp0;
|
||||
dp0=Math.max(dp0,dp1);
|
||||
dp1=Math.max(dp1,dp2+prices[i]);
|
||||
dp2=Math.max(dp2,temp0-prices[i]);
|
||||
}
|
||||
|
||||
return Math.max(dp0,dp1);
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue