leetcode(121)(122)(123)(188) Best Time to Buy and Sell Stock I/II/III/IV JAVA代码
来源:互联网 发布:matlab编程第刘卫国 编辑:程序博客网 时间:2024/06/05 02:53
原题链接:
https://leetcode.com/problems/best-time-to-buy-and-sell-stock
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-II
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-III
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-IV
第一题
这道题比较简单,只允许交易一次,得到最大收益。只要找到两天价格差最大即可
按照此思路,代码如下:
package leetcode;public class BestTimetoBuyAndSellStock {// https://leetcode.com/problems/best-time-to-buy-and-sell-stock/public static int maxProfit(int[] prices) {int len = prices.length;if (prices == null || len <= 1) {return 0;}int minPrice = prices[0]; // 最小价格初始化int diff = prices[1] - prices[0];// 价格差for (int i = 2; i < len; i++) {minPrice = Math.min(prices[i-1], minPrice);if(diff<prices[i]-minPrice){diff=prices[i]-minPrice;}}if(diff<0){return 0;}return diff;}public static void main(String[] args) {// TODO Auto-generated method stubint[] prices = { 1, 3, 5, 6, 1, 2, 9 };System.out.println(maxProfit(prices) + "");}}
还有一种解法,维护两个变量,一个代表当前最大收益local,一个代表全局最大收益global,local是上一次当前收益加上后面两天收益的价差得到,全局收益是指全局收益与此次当前收益取最大值。这样,local的值实质上是此时卖出价格与第一次买入时的价差,global可以记录价差的最大值。大家可以运行代码单步调试来理解这个方法,代码如下:
package leetcode;public class BestTimetoBuyAndSellStock {// https://leetcode.com/problems/best-time-to-buy-and-sell-stock/public static int maxProfit(int[] prices) {if (prices == null || prices.length <= 1) {return 0;}int local = 0;int global = 0;for (int i = 0; i < prices.length - 1; i++) {local = Math.max(local + prices[i + 1] - prices[i], 0);// 当前最大收益global = Math.max(local, global);// 全局最大收益}return global;}public static void main(String[] args) {// TODO Auto-generated method stubint[] prices = { 1, 3, 5, 6, 1, 2, 9 };System.out.println(maxProfit(prices) + "");}}
第二题:
这里同第一次差别为可以购买无数次,这道题可以这样想,根据第一题第二种解法,可以知道当前最大收益本地值,当时只允许买卖一次,所以用一个global来记录最大收益。现在可以允许买卖无数次,所以不需要global去记录最大收益,只要收益为正的时候,就可以进行买入卖出。,所以只要前后两次价差为正即可加到收益中去。代码如下:
package leetcode;import java.lang.reflect.Array;public class BestTimeToBuyAndSellStockII {// https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/public static int maxProfit(int[] prices) {if (prices == null || prices.length == 0) {return 0;}int len = prices.length;int maxProfit = 0;for (int i = 1; i < len; i++) {int tempProfit = prices[i] - prices[i - 1];if (tempProfit > 0) {maxProfit += tempProfit;}}return maxProfit;}public static void main(String[] args) {// TODO Auto-generated method stubint[] prices = { 1 };System.out.println(maxProfit(prices) + "");}}
第三题:
可以买入两次。这时可以用动态规划的算法来做了,但是我到第四题的时候可以买入k次条件时再用动态规划,这里用另外一种方法。
这里我们创建两个数组ArrayA与ArrayB,一个记录从前向后遍历得到的最大价差,一个记录从后向前遍历得到的最大价差。最后两个相加后得到的最大值即为最大收益。代码如下:
package leetcode;public class BestTimetoBuyAndSellStockIII {// https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/public static int maxProfit(int[] prices) {if (prices == null || prices.length == 0) {return 0;}int len = prices.length;int sum = 0;int min = prices[0];int[] ArrayA = new int[len];for (int i = 1; i < prices.length; i++) {ArrayA[i] = prices[i] - min;ArrayA[i] = ArrayA[i] > ArrayA[i - 1] ? ArrayA[i] : ArrayA[i - 1];if (prices[i] < min) {min = prices[i];}}int max = prices[prices.length - 1];int[] ArrayB = new int[len];for (int i = len - 1; i > 0; i--) {ArrayB[i] = max - prices[i];ArrayB[i] = ArrayB[i] > ArrayB[i - 1] ? ArrayB[i] : ArrayB[i - 1];if (prices[i] > max) {max = prices[i];}}for (int i = 0; i < len; i++) {sum = Math.max(ArrayA[i] + ArrayB[i], sum);}return sum;}public static void main(String[] args) {// TODO Auto-generated method stubint[] prices = { 1, 3, 5, 6, 1, 2, 9 };System.out.println(maxProfit(prices) + "");}}这个思路很容易理解,前后两次价差相加。
第四题:
买入k次,这次就只能用动态规划的思想了。之前不了解动态规划的同学,可以先看背包问题九讲!!!,讲的很好,之后我也回把背包问题的代码贴出来。
背包问题九讲链接地址:http://love-oriented.com/pack/(必看)
首先先按照第二题思路,求得最大收益值与最大交易次数(无限次条件)。如果交易次数k大于最大交易次数,则最终结果就是最大收益。
如果k小于最大交易次数,则使用动态规划的方法求解收益最大值。
第四题代码:
package leetcode;public class BestTimetoBuyAndSellStockIV {// https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/public static int maxProwt(int k, int[] prices) {int days = prices.length;int tradeCount = 0;// 交易次数int profitCount = 0;// 收益int rangeProfitCount = 0;for (int i = 1; i < days; i++) {if (prices[i - 1] < prices[i]) {// 两天之间收益为正值rangeProfitCount += prices[i] - prices[i - 1];if (i == days - 1) {// 最后一天profitCount += rangeProfitCount;tradeCount += 1; // 交易次数加一}} else if (rangeProfitCount > 0) {profitCount += rangeProfitCount; // 收益加上tradeCount += 1; // 交易次数加一rangeProfitCount = 0;}}if (k >= tradeCount) {// 如果k交易次数大于等译交易总次数,直接返回最大收益return profitCount;}int[][] global = new int[k + 1][days];int[][] local = new int[k + 1][days];// 动态规划for (int i = 1; i <= k; i++) {for (int j = 1; j < days; j++) {int diff = prices[j] - prices[j - 1];local[i][j] = Math.max(global[i - 1][j - 1], local[i][j - 1] + diff);global[i][j] = Math.max(global[i][j - 1], local[i][j]);}}return global[global.length - 1][global[0].length - 1];}public static void main(String[] args) {// TODO Auto-generated method stubint[] prices = { 1, 3, 5, 6, 1, 2, 9 };System.out.println(maxProwt(3, prices) + "");}}
附:背包问题代码(包含01背包,完全背包,多重背包求解方法)
package pack;import java.util.ArrayList;import java.util.List;import org.omg.CORBA.SystemException;public class Pack {private static int N = 4; // 物品个数private static int V = 10; // 背包最大容量private int[] f;// 前i件物品放入容量为j的背包得到的最大价值f[j]private static int G=2;//分组背包问题组数// 状态转移方程f[v]=max{f[v],f[v-cost]+weight};public Pack() {super();resetF();}private void resetF() {f = new int[V + 1];for (int i = 0; i < f.length; i++) {f[i] = 0;}}/** * 01背包 * * @param cost * 消耗容量 * @param weight * 体积 * @return */private void ZeroOnePack(int cost, int weight) {for (int v = V; v >= cost; v--) {f[v] = Math.max(f[v], f[v - cost] + weight);}}/** * 完全背包 * * @param cost * 消耗容量 * @param weight * 体积 * @return */private void CompletePack(int cost, int weight) {for (int v = cost; v <= V; v++) {f[v] = Math.max(f[v], f[v - cost] + weight);}}/** * 多重背包 * * @param cost * @param weight * @param amount */private void MultiplePack(int cost, int weight, int amount) {if (cost * amount >= V) {CompletePack(cost, weight);return;}int k = 1;while (k < amount) {ZeroOnePack(k * cost, k * weight);amount = amount - k;k = k * 2;}ZeroOnePack(amount * cost, amount * weight);}public static void main(String[] args) {// TODO Auto-generated method stubint[] cost = { 6, 3, 4, 2 };int[] weight = { 30, 14, 16, 9 };int[] amount = { 0, 1, 2, 3 };Pack zo = new Pack();/************01背包************/zo.resetF();for (int i = 0; i < N; i++) {zo.ZeroOnePack(cost[i], weight[i]);}System.out.println(zo.f[V] + "");/************完全背包 ************/zo.resetF();for (int i = 0; i < N; i++) {zo.CompletePack(cost[i], weight[i]);}System.out.println(zo.f[V] + "");/************多重背包************/zo.resetF();for (int i = 0; i < N; i++) {zo.MultiplePack(cost[i], weight[i], amount[i]);}System.out.println(zo.f[V] + "");}}
同时还有一篇讲动态规划的文章推荐给大家:http://www.cnblogs.com/sdjl/articles/1274312.html
同时附录出文章中的C++代码:
#include<iostream>#include<fstream>using namespace std;//http://www.cnblogs.com/sdjl/articles/1274312.htmlconst int max_n=100;//程序支持的最多金矿数const int max_people=10000;//程序支持的最多人数int n;//金矿数int peopleTotal;//可以用于挖金子的人数int peopleNeed[max_n];//每座金矿需要的人数int gold[max_n];//每座金矿能够挖出来的金子数int maxGold[max_people][max_n];//maxGold[i][j]保存了i个人挖前j个金矿能够得到的最大金子数,等于-1表示未知//初始化数据void init(){ ifstream inputFile("beibao.in"); inputFile>>peopleTotal>>n; for(int i=0;i<n;i++){ inputFile>>peopleNeed[i]>>gold[i]; } inputFile.close(); for(int i=0;i<=peopleTotal;i++){ for(int j=0;j<n;j++){ maxGold[i][j]=-1;//等于-1时表示未知 } }}//获得在仅有people个人和前mineNum个金矿时能够得到的最大金子数int GetMaxGold(int people,int mineNum){ int retMaxGold; //返回的最大金子数 if(maxGold[people][mineNum]!=-1){//如果曾经这个问题已经计算过 retMaxGold=maxGold[people][mineNum];//获得保存起来的值 } else if(mineNum==0){//如果仅有一个金矿 if(people>peopleNeed[mineNum]){ retMaxGold=gold[mineNum]; }else{//否则一个矿也不能开采 retMaxGold=0; } } else if(people>=peopleNeed[mineNum]){//人数够开采此矿 retMaxGold=max(GetMaxGold(people-peopleNeed[mineNum],mineNum-1)+gold[mineNum],GetMaxGold(people,mineNum-1));//两种情况,要么开采此矿剩下的人采其它矿;要么不开采此矿,所有人开采下一个矿.两者取最大值 } else{//剩下的人无法开采此矿,直接开采下一个矿 retMaxGold=GetMaxGold(people,mineNum-1); } maxGold[people][mineNum]=retMaxGold;//记录下当前人数能采mineNum号矿的最大值 return retMaxGold;}int main(){ init(); cout<<GetMaxGold(peopleTotal,n-1); //return 0;}
- leetcode(121)(122)(123)(188) Best Time to Buy and Sell Stock I/II/III/IV JAVA代码
- [Leetcode] #121#122#123#188 Best Time to Buy and Sell Stock I & II & III & IV
- LeetCode OJ Best Time to Buy and Sell Stock I II III IV
- LeetCode - Best Time to Buy and Sell Stock I && II && III && IV
- 【LeetCode】 Best Time to Buy and Sell Stock I II III IV 解题报告
- LeetCode-Best Time to Buy and Sell Stock I II III IV
- 【LeetCode】 Best Time to Buy and Sell Stock I II III IV 解题报告
- [LeetCODE] Best Time to Buy and Sell Stock I II III IV V
- leetcode笔记--Best Time to Buy and Sell Stock系列(I,II, III, IV)
- LeetCode - Best Time To Buy and Sell Stock Series (I, II, III, IV, with Cooldown)
- [LeetCode] Best Time to Buy and Sell Stock I II III IV
- [LeetCode] Best Time to Buy and Sell Stock I II III IV 股票买卖
- 【LeetCode】 best-time-to-buy-and-sell-stock-i ii iii iv
- LeetCode Best Time to Buy and Sell Stock I & II & III & IV
- 121. Best Time to Buy and Sell Stock & 122 II & 123 III & 188 IV
- LeetCode 121, 122, 123. Best Time to Buy and Sell Stock i, ii, iii
- LeetCode 121-123 Best Time to Buy and Sell Stock I II III
- leetcode_[python/C++]_121/122/123/188.Best Time to Buy and Sell Stock I/II/III/IV
- html5
- 接口的实现案列
- 小米盒子adb 权限
- Jeecg 学习笔记
- eclipse项目遇到红色叹号,该如何解决?
- leetcode(121)(122)(123)(188) Best Time to Buy and Sell Stock I/II/III/IV JAVA代码
- Android下的下拉列表框Spanner
- Android Fragment传递参数Fragment.setArguments(Bundle bundle)
- 【Java】面向对象思想以及类与对象的关系
- SpringMVC Controller 介绍
- Unity自带的SimpleJSon的简单使用
- centos7 菜鸟第一天--输入法在哪
- 有 1 、 2 、 3 、 4 个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
- Android 图片模糊 性能总结