LeetCode 188. Best Time to Buy and Sell Stock IVsolution
Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most k transactions. Note:You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). Credits:Special thanks to @Freezen for adding this problem and creating all test cases. Subscribe to see which companies asked this question.
假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。 设计一个算法来找到最大的利润。你最多可以完成 k 笔交易。 样例 给定价格 = [4,4,6,1,1,4,2,5], 且 k = 2, 返回 6.
solution
典型的动态规划,并且利用局部和全局最优,这种思想值得仔细体会,好好掌握。 这种局部最优与全局最优问题 global[i][j] = max(local[i][j], global[i - 1][j]) 很容易知道上面这个递推式。 关键在于求取局部最优的递推式,在本题中 local[i][j] = max(global[i - 1][j - 1] + max(diff, 0), local[i - 1][j] + diff) 这里我们需要两个递推公式来分别更新两个变量local和global 我们定义local[i][j]为在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,此为局部最优。然后我们定义global[i][j]为在到达第i天时最多可进行j次交易的最大利润,此为全局最优 局部最优解的递推式可以这样理解:
- 在i-1天时,正在进行第j次交易,所以我们最后一天必须将股票卖出,而且这是算在第j次交易当中的,这种情况下,local[i - 1][j] + diff,只需将i-1天的局部最优解加上最后一天卖出的差值即可,相当于将最后一次交易多延迟了一天
- 第二种情况,就是在第i-1天进行j-1次交易的全局最优解,我们在最后一天还得进行一次交易,必须卖出,如果diff大于0,那么就在第i-1天买进,i天卖出,如果小于0,就直接在第i天买进又卖出,只是为了满足j次交易,就相当于没有交易,即加上0就可以了。 这道题还有一个陷阱,可以优化的地方,就是如果k>=prices.length/2。那我们可以理解可以进行任意次交易了,因为有效交易都需要两天来完成,所以直接使用贪心法就可以算出来了。
public int maxProfit(int k, int[] prices) {
int len = prices.length;
if(k <=0 || len < 2)
return 0;
int maxProfit = 0;
if(k >= len/2) {
//直接当作贪心处理,也就是问题2的答案
for(int i=1;i<len;i++) {
int diff = prices[i]-prices[i-1];
if(diff > 0)
maxProfit += diff;
}
return maxProfit;
}
int[][] local = new int[len][k+1];
int[][] global = new int[len][k+1];
for(int i=1;i<len;i++) {
int diff = prices[i] - prices[i-1];
for(int j=1;j<=k;j++) {
local[i][j] = Math.max(global[i-1][j-1] + Math.max(diff, 0),
local[i-1][j] + diff);
global[i][j] = Math.max(local[i][j], global[i-1][j]);
}
}
return global[len-1][k];
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- AndroidStudio 设置格式化断行宽度教程
- 从 SpringBoot 到 SpringMVC
- AndroidManifest.xml中含盖的安全问题详解
- Android Studio实现格式化XML代码顺序
- android自动生成dimens适配文件的图文教程详解(无需Java工具类)
- Android Studio自动提取控件Style样式教程
- 基于Android studio3.6的JNI教程之ncnn人脸检测mtcnn功能
- Kotlin 使用Lambda来设置回调的操作
- Kotlin之自定义 Live Templates详解(模板代码)
- Android Studio设置颜色拾色器工具Color Picker教程
- Kotlin中常见的符号详解
- Kotlin中实体类的创建方式
- Android自定义流式布局/自动换行布局实例
- Android 中 MD5 的几种生成方式(小结)
- Flutter 日期时间DatePicker控件及国际化