赞
踩
//1)贪心题解 public int maxProfit(int[] prices) { //1)遍历 int min=prices[0]; //找出i索引之前最小值 int max=0; //找出i索引之前dp的最大值 for(int i=1;i<prices.length;i++){ min=Math.min(prices[i],min); max=Math.max(prices[i]-min,max); } return max; }``` ```java //2)动态规划题解 public int maxProfit(int[] prices) { //动规分为两种状态 //dp[i][0]:在i时刻,持有股票,手上的钱最大值,用最低的钱买到股票 //dp[i][1]:在i时刻,不持有股票,手上的钱最大值 //0)特殊情况 if(prices.length==1) return 0; //1)新建并初始化dp int[][] dp=new int[prices.length][2]; dp[0][0]=-prices[0]; //持有股票,即在该时刻买入 dp[0][1]=0; //不持有,即前面不可能有买入,故为0 //2)遍历 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]);//要么是之前就卖出了,不持有;要么就是现在才卖出的 } //3)输出 return dp[prices.length-1][1]; }
题目描述
解题思路
1)贪心思想
(1):由于可以交易多次,并且没有手续费,故只有后者比前者大,就可以进行一次买入卖出操作
(2):可以从i=1开始,如果prices[i] -prices[i-1],那么可以在i 时刻进行卖出操作
2)动态规划思想(为后面的题目做铺垫):骨片存在两种状态(持有和不持有)
(1):持有状态:dp[ i ][ 0 ]= Math.max( dp[ i-1 ][ 0 ] ,dp[ i -1][ 1 ] -prices[ i ]); //注意:由于存在多次交易,故为未持有装填减去prices[ i ],这也是和题目一的区别。
(2):未持有状态:dp[ i ][ 1 ]= Math.max( dp[ i-1 ][ 1 ] ,dp[ i-1 ][ 0 ]+prices[ i ]);## 2.3. 题目三:121.买卖股票的最佳时机
代码详解
//1)贪心思想
public int maxProfit(int[] prices) {
//1)得到一个后者减去前者的数组
int[] cha=new int[prices.length];
int result=0;
for(int i=1;i<prices.length;i++){
cha[i]=prices[i]-prices[i-1];
if(cha[i]>=0) result+=cha[i];
}
//System.out.println(Arrays.toString(cha));
return result;
}
//2)动态规划思想 public int maxProfit(int[] prices) { //动态规划方法:和之前的只差在持有股票上面 //0)特殊情况 if(prices.length==1) return 0; //1)dp数组的定义和初始化 int [][] dp=new int[prices.length][2]; dp[0][0]=-prices[0]; //持有股票时 dp[0][1]=0; //不持有股票时 //2)遍历 for(int i=1;i<prices.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]); //和之前一样 } //3)输出 return dp[prices.length-1][1]; //不持有股票,钱最多
题目描述
解题思路
1)首先和股票问题二很像,只是有两笔交易故有五种状态
(0):状态一:dp[i][0]:无交易状态
(1):状态二:dp[i][1]:第一笔交易,持有股票 :比较【dp[i-1][1],dp[i-1][0]-prices[i ] 】
(2):状态二:dp[i][2]:第一笔交易,不持有股票:比较【dp[i-1][2],dp[i-1][1]+prices[i ] 】
(3):状态二:dp[i][3]:第二笔交易,持有股票:比较【dp[i-1][3],dp[i-1][2]-prices[i ] 】
(4):状态二:dp[i][4]:第二笔交易,不持有股票:比较【dp[i-1][4],dp[i-1][3]+prices[i ] 】
2)针对五种状态进行迭代,然后最大的状态为dp[i][4]。
代码详解
//1)普通模式 public int maxProfit(int[] prices) { //延续上一题股票买卖的思路 //1)dp[i][0]:不操作 //2)dp[i][1]:第一次买入 //3)dp[i][2]:第一次卖出 //4)dp[i][3]:第二次买入 //5)dp[i][4]:第一次卖出 //1)特殊情况 if(prices.length==1) return 0; //2)dp的初始化与定义 int[][] dp=new int [prices.length][5]; //for(int i=1;i<5;i++) dp[0][i]=-prices[0]; dp[0][1]=-prices[0]; dp[0][3]=-prices[0]; //3)遍历 for(int i=1;i<prices.length;i++){ dp[i][0]=dp[i-1][0]; //不操作,就一直保持零 dp[i][1]=Math.max(dp[i-1][0]-prices[i],dp[i-1][1]); //第一次买入的最低价 dp[i][2]=Math.max(dp[i-1][1]+prices[i],dp[i-1][2]); //第一次卖出的最高价 dp[i][3]=Math.max(dp[i-1][2]-prices[i],dp[i-1][3]); //第二次买入的最低价 dp[i][4]=Math.max(dp[i-1][3]+prices[i],dp[i-1][4]); //第二次卖出的最低价 } //4)输出 return dp[prices.length-1][4]; }
//采用for循环的模式,方便后面修改为多次股票交易 public int maxProfit(int[] prices) { //延续上一题股票买卖的思路 //1)dp[i][0]:不操作 //2)dp[i][1]:第一次买入 //3)dp[i][2]:第一次卖出 //4)dp[i][3]:第二次买入 //5)dp[i][4]:第一次卖出 //1)特殊情况 if(prices.length==1) return 0; //2)dp的初始化与定义 int[][] dp=new int [prices.length][5]; for(int i=1;i<5;i+=2) dp[0][i]=-prices[0]; //3)遍历 for(int i=1;i<prices.length;i++){ dp[i][0]=dp[i-1][0]; //不操作,就一直保持零 for(int j=1;j<5;j++){ if(j%2==1){ //奇数买入 dp[i][j]=Math.max(dp[i-1][j-1]-prices[i],dp[i-1][j]); }else{ //偶数买入 dp[i][j]=Math.max(dp[i-1][j-1]+prices[i],dp[i-1][j]); } } } //4)输出 return dp[prices.length-1][4]; }
题目描述
解题思路
1)这一题和上一题一模一样,只是需要修改一下k值
2)核心思路是:记录每一次交易的转态,如果有K笔交易,故需要有2*K+1种状态。
代码详解
public int maxProfit(int k, int[] prices) { //1)特殊情况 if(prices.length<=1 ||k==0) return 0; //2)dp的定义和初始化 int[][] dp=new int[prices.length][2*k+1]; for(int i=1;i<2*k+1;i+=2) dp[0][i]=-prices[0]; //3)迭代递归 for(int i=1;i<prices.length;i++){ for(int j=1;j<2*k+1;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]); } } } //4)输出 return dp[prices.length-1][2*k]; }
public int maxProfit(int[] prices) { //0)特殊情况 if(prices.length==1) return 0; //1)dp数组的定义 int[][] dp=new int[prices.length][4]; dp[0][0]=-prices[0]; //持有股票,购买没有操作;或者今天购买的股票(前一天为持有状态,前一天为冷冻期,前一天为过了冷冻期) dp[0][1]=0; //不持有股票,今天卖出的(前一天为持有股票状态) dp[0][2]=0; //不持有股票,冷冻期(前一天为当天卖出股票) dp[0][3]=0; //不持有股票,不是今天卖出的,度过了冷冻期(前一天为冷冻期,前一天为度过冷冻期) //3)迭代遍历 for(int i=1;i<prices.length;i++){ dp[i][0]=Math.max(dp[i-1][0],Math.max(dp[i-1][2]-prices[i],dp[i-1][3]-prices[i]));//三种情况 dp[i][1]=dp[i-1][0]+prices[i]; //一种情况 dp[i][2]=dp[i-1][1]; //一种情况 dp[i][3]=Math.max(dp[i-1][1], dp[i-1][3]); //两种情况 } //4)结果 //结果再三个地方都可以,只要是处于不持有股票状态 return Math.max(dp[prices.length-1][1],Math.max(dp[prices.length-1][2],dp[prices.length-1][3])); }
public int maxProfit(int[] prices, int fee) { //动态规划算法,维持两种状态即可 //1)特殊 int size=prices.length; if(size==1) return 0; //2)dp的定义与初始化 int[][] dp=new int[size][2]; dp[0][0]=-prices[0]; //在这个时刻如果是持有股票 dp[0][1]=0; //在这个时刻如果是不持有股票 //3)遍历和迭代 for(int i=1;i<size;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]-fee); //和题目二不一样的地方 } //4)输出 return dp[size-1][1]; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。