今天我做了LintCode上的买卖股票系列题目。总共4道题目,主要使用了动态规划的方法,在此写出我的代码和思路以便交流和回顾。

1.假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格。如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润。

样例:给出一个数组样例 [3,2,3,1,2], 返回 1

思路:遍历数组,在能获利的地方尝试卖出,并比较卖出利润是否最大。在成本更低的地方则买入。

class Solution {
public:/*** @param prices: Given an integer array* @return: Maximum profit*/int maxProfit(vector<int> &prices) {// write your code hereif(prices.size() == 0){ //时刻注意数组越界return 0;}int max = 0;int cur = prices[0];for(int i = 0; i < prices.size(); ++i){if(prices[i] < cur){ //卖掉会亏cur = prices[i];}else{ //卖掉能挣int tmp = prices[i] - cur;if(tmp > max){max = tmp;}}}return max;}
};

2.假设有一个数组,它的第i个元素是一个给定的股票在第i天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交易(你必须在再次购买前出售股票)。

样例:给出一个数组样例[2,1,2,0,1], 返回 2

思路:由于买卖次数无限,所以只要能获利就进行买卖,这样能保证所有利润都吃到自然利润最大。

class Solution {
public:/*** @param prices: Given an integer array* @return: Maximum profit*/int maxProfit(vector<int> &prices) {// write your code hereint i, d;int max = 0;for(i = 1; i < prices.size(); ++i){//只要有钱赚就买卖d = prices[i] - prices[i - 1];if(d > 0){max += d;}}return max;}
};

3.假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。 设计一个算法来找到最大的利润。你最多可以完成两笔交易。

样例:给出一个样例数组 [4,4,6,1,1,4,2,5], 返回 6

思路:使用递推的方法,先计算第一次买卖的最大利润区间,第二次买卖是要想获得最大利润,要么是在第一次买卖的区间之前再进行一次最大利润买卖,要么是在第一次买卖的区间之后再进行一次最大利润买卖,要么是从第一次买卖的区间中切除一个最大亏损区间,将其切分成两次买卖。比较三种方案哪种带来的利润最多就可以得到两笔交易后的最大利润。计算最大利润区间使用题1的算法,计算最大亏损区间只要改变一下题1算法的符号。

struct Sub{ //买卖区间int begin;int end;bool fill;Sub(int begin = 0, int end = 0, bool fill = true){this->begin = begin;this->end = end;this->fill = fill;}
};class Solution {
public:/*** @param prices: Given an integer array* @return: Maximum profit*/int maxProfit(vector<int> &prices) {if(prices.size() == 0){return 0;}Sub tmpSub;//第一次买卖后的最大利润int max = findMaxSub(prices, 0, prices.size() - 1, tmpSub);//第二次买卖后的最大利润vector<Sub> subArr;subArr.push_back(tmpSub);subArr.push_back(Sub(0, tmpSub.begin - 1, false));subArr.push_back(Sub(tmpSub.end + 1, prices.size() - 1, false));int maxSub = 0;for(int i = 0; i < subArr.size(); ++i){int tmp;if(subArr[i].fill){tmp = -findMinSub(prices, subArr[i].begin, subArr[i].end, tmpSub);}else{tmp = findMaxSub(prices, subArr[i].begin, subArr[i].end, tmpSub);}if(tmp > maxSub){maxSub = tmp;}}return max + maxSub;}int findMaxSub(vector<int> &arr, int begin, int end, Sub& sub) {if(begin >= end)return 0;sub.fill = true;int r = 0;int curIndex = begin;for(int i = begin; i <= end; ++i){if(arr[i] < arr[curIndex]){curIndex = i;}else{int tmp = arr[i] - arr[curIndex];if(tmp > r){r = tmp;sub.end = i;sub.begin = curIndex;}}    }return r;}int findMinSub(vector<int> &arr, int begin, int end, Sub& sub) {if(begin >= end)return 0;sub.fill = false;int r = 0;int curIndex = begin;for(int i = begin; i <= end; ++i){if(arr[i] > arr[curIndex]){curIndex = i;}else{int tmp = arr[i] - arr[curIndex];if(tmp < r){r = tmp;sub.end = i;sub.begin = curIndex;}}    }return r;}
};

4.假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来找到最大的利润。你最多可以完成 k 笔交易。 样例:给定价格 =[4,4,6,1,1,4,2,5], 且 k = 2, 返回 6.

思路:是题3方法的推广,需要注意的是在交易已经无法再提高利润时要退出循环以提高算法速度。网上有讨论认为在k大于数组长度的情况下直接使用题2的方法计算利润更有效率,也有与我不同的动态规划思路可以提高效率。参考:http://www.cnblogs.com/grandyang/p/4295761.html

struct Sub{//买卖区间int begin;int end;bool fill;Sub(int begin = 0, int end = 0, bool fill = true){this->begin = begin;this->end = end;this->fill = fill;}
};class Solution {
public:/*** @param prices: Given an integer array* @return: Maximum profit*/int maxProfit(int k, vector<int> &prices) {int max = 0;vector<Sub> subArr;subArr.push_back(Sub(0, prices.size() - 1, false));while(k--){//寻找一次最有利的切分int maxCount = 0;int maxIndex = -1;Sub maxSub;Sub tmpSub;for(int i = 0; i < subArr.size(); ++i){int tmp;if(subArr[i].fill){//在实心区间上挖下一个最小值tmp = -findMinSub(prices, subArr[i].begin, subArr[i].end, tmpSub);}else{//在空心区间上找最大利润区间tmp = findMaxSub(prices, subArr[i].begin, subArr[i].end, tmpSub);}if(tmp > maxCount){//记录下当前最佳划分方式和其带来的利润maxCount = tmp;maxIndex = i;maxSub = tmpSub;}}//计算切分之后的区间状态if(maxIndex >= 0){Sub sub = subArr[maxIndex];if(sub.fill){subArr.push_back(Sub(sub.begin, maxSub.begin, true));subArr.push_back(Sub(maxSub.end , sub.end, true));maxSub.begin += 1;maxSub.end -= 1;subArr[maxIndex] = maxSub;}else{subArr.push_back(Sub(sub.begin, maxSub.begin - 1, false));subArr.push_back(Sub(maxSub.end + 1, sub.end, false));subArr[maxIndex] = maxSub;}//计算此次切分之后的最大利润max += maxCount;}else{ //若无法再切分则退出循环break;}}return max;}int findMaxSub(vector<int> &arr, int begin, int end, Sub& sub) {if(begin >= end)return 0;sub.fill = true;int r = 0;int curIndex = begin;for(int i = begin; i <= end; ++i){if(arr[i] < arr[curIndex]){curIndex = i;}else{int tmp = arr[i] - arr[curIndex];if(tmp > r){r = tmp;sub.end = i;sub.begin = curIndex;}}    }return r;}int findMinSub(vector<int> &arr, int begin, int end, Sub& sub) {if(begin >= end)return 0;sub.fill = false;int r = 0;int curIndex = begin;for(int i = begin; i <= end; ++i){if(arr[i] > arr[curIndex]){curIndex = i;}else{int tmp = arr[i] - arr[curIndex];if(tmp < r){r = tmp;sub.end = i;sub.begin = curIndex;}}    }return r;}
};

LintCode 买卖股票的最佳时机I II III IV相关推荐

  1. 买卖股票的最佳时机 I II III IV

    121. 买卖股票的最佳时机 自己的思路:采用求最长连续子串和题目的思路 class Solution {public int maxProfit(int[] prices) {if(prices.l ...

  2. lintcode:买卖股票的最佳时机 III

    买卖股票的最佳时机 III 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 样例 给出一个样例数组 [4,4,6,1,1,4,2 ...

  3. lintcode - 买卖股票的最佳时机 III

    题目描述:假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 样例:给出一个样例数组 [4,4,6,1,1,4,2,5], 返回 6 ...

  4. 力扣记录:动态规划4股票问题——121,122,123,188 ,309,714买卖股票的最佳时机(I,II,III,IV,含冷冻期,含手续费)

    本次题目 121 买卖股票的最佳时机(只能买卖一次) 122 买卖股票的最佳时机II(可以买卖多次) 123 买卖股票的最佳时机III(最多买卖两次) 188 买卖股票的最佳时机IV(最多买卖k次) ...

  5. LintCode领扣算法问题答案:150. 买卖股票的最佳时机 II

    150. 买卖股票的最佳时机 II 描述 给定一个数组 prices 表示一支股票每天的价格. 你可以完成任意次数的交易, 不过你不能同时参与多个交易 (也就是说, 如果你已经持有这支股票, 在再次购 ...

  6. 122. 买卖股票的最佳时机 II

    121. 买卖股票的最佳时机 122. 买卖股票的最佳时机 II 123. 买卖股票的最佳时机 III 188. 买卖股票的最佳时机 IV 309. 最佳买卖股票时机含冷冻期 714. 买卖股票的最佳 ...

  7. 算法训练第五十天 | 123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV

    动态规划part11 123.买卖股票的最佳时机III 题目描述 思路 拓展 188.买卖股票的最佳时机IV 题目描述 思路 易错点 123.买卖股票的最佳时机III 题目链接:123.买卖股票的最佳 ...

  8. 买卖股票的最佳时机III

    思路 这道题目相对 121.买卖股票的最佳时机 和 122.买卖股票的最佳时机II 难了不少. 关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖. 确定dp数组以及下标的含义 一 ...

  9. 买卖股票的最佳时机II

    思路 本题和121. 买卖股票的最佳时机的唯一区别本题股票可以买卖多次了(注意只有一只股票,所以再次购买前要出售掉之前的股票) 这里重申一下dp数组的含义: dp[i][0] 表示第i天持有股票所得现 ...

最新文章

  1. 矩阵推导后注意力机制居然是这样
  2. Application ProvidedAar 完结篇
  3. 学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本
  4. linux shell之字符串的更具字符分割和删除字符和文本内容的删除以及内容是否匹配成功
  5. pip 查看要安装的包所有版本(所有包版本)
  6. android判断是否已经安装成功,android 判断应用程序是否已安装
  7. 洛谷P1098 字符串的展开【字符串】【模拟】
  8. 【实物】端到端自动驾驶搭建教程(一)附完整资料
  9. 锐捷交换机-负载均衡方式配置说明
  10. python处理excel教程视频-从零基础开始用Python处理Excel数据 视频教程
  11. 如何打开和修改CAJ格式的文档?
  12. 滑动窗口算法思想,找出字符串中的所有字母异位词
  13. 夜晚,我路过那座城市
  14. ROS 机器人操作系统
  15. 2021-2027全球与中国3,5-二氯-4-甲基吡啶市场现状及未来发展趋势
  16. 乘车码连不上系统服务器,支付宝乘车码无法开通的原因及开通步骤详解
  17. mysql好友关系数据表设计_社交系统中用户好友关系数据库设计
  18. pop()函数的用法
  19. 微信小程序自定义canvas手写签名组件
  20. 3个月不用,当心你的微信公众号将被冻结!

热门文章

  1. Oracle Cloud云端账号的注册过程
  2. 自动化测试元素定位方式之find_elements_by_XXX()定位
  3. 详解pandas中的groupy机制
  4. 【小睿精选·第八期】为NBA球员提供预警新冠肺炎的智能戒指Oura Ring
  5. 如何打造良好的技术团队分享氛围
  6. 什么是好的技术氛围?
  7. 百度手环开源 51822开发套件
  8. 计算机网络之计算机网络概述
  9. 安卓实训运动健身系统_武汉一高校现高颜值网红健身打卡地
  10. 通俗解释色相和饱和度和明度