IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 从股票买卖引申出来的几种思想(面试必看) -> 正文阅读

[数据结构与算法]从股票买卖引申出来的几种思想(面试必看)

? 股票买卖这个算法话题可以说是在基础算法这一块是一个很有意思的存在了。题目稍微变一些或许就回要以完全不同的眼光去看待这个问题。话不多说,一起来看看...

给定一个数组 prices ,它的第?i 个元素?prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

输入:[7,1,5,3,6,4]

输出:5

思路分析:对数组的每一项都有一个确定的最大利润。获得的方式就是,用当前值减去之前出现的最小值。(当然这种股票买法肯定不可能了是吧)。因此就用两个变量来分别动态表示最小值minprice和最大利润max。遍历一遍数组就是不是就可以了呢?

var maxProfit = function(prices) {
    let minprice=Number.MAX_SAFE_INTEGER
    let max=0
    for(let i=0;i<prices.length;i++){
        if(prices[i]<minprice){
            minprice=prices[i]
        }else if(prices[i]-minprice>max){
            max=prices[i]-minprice
       }
    }
    return max
};

?这其实就是类似双指针的思想了。

那假设你可以无限次地完成交易,但是你每笔交易都需要付手续费fee。并且如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

?很容易想到的是贪心算法,只要有我一次买入卖出的利润减去fee之后还有剩余那么我就赚了,事实上这样的思想可能并不会带来全局最优解,因为第二天还是递增的话那么买入卖出还得交出手续费。所以还得判断一下第二天是否还是递增的。

?

?

可以采用一个巧妙的思想:将手续费在买入的时候交出,而不是卖出。维护一个buy变量为prices[i]+fee,遍历数组并且更新buy为最小。另外假如prices[i]大于buy那么就可以获得利润,但是为了防止之后会有递增的prices[i],因此此时buy更新为prices[i],而不是prices[i]+fee。

var maxProfit = function(prices, fee) {
    let buy=prices[0]+fee
    let max=0
    for(let i=1;i<prices.length;i++){
        if(prices[i]+fee<buy){
            buy=prices[i]+fee
        }else if(prices[i]>buy){
            max+=prices[i]-buy
            //考虑到之后有prices[i]递增
            buy=prices[i]
        }
    }
    return max
}

除此之外还可以用动态规划来解决。分析一下状态可以知道,第i+1天只有两种状态,手上有股票以及手上没有股票,所以定义一个二维数组。dp[i][0]代表手上没有股票时的最大收益。dp[i][1]代表手上有股票时的最大收益。

那么递归方程就很好写了,dp[i][0]可能是由于dp[i-1][0],也可能是dp[i][0]+prices[i]-fee把股票卖了。两者取大值。

dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]-fee)

同理可以得到:

dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i])

边界条件的话就是dp[0][0]=0,dp[0][1]=-prices[0],可以得到代码:

var maxProfit = function(prices, fee) {
    let dp=new Array(prices.length).fill(0).map(item=>new Array(2).fill(0))
    dp[0][0]=0,dp[0][1]=-prices[0]
    for(let i=1;i<prices.length;i++){
        dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]-fee)
        dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i])
    }
    return Math.max(dp[prices.length-1][0],dp[prices.length-1][1])
};

ok,继续修改题目...如果不考虑手续费怎么做呢?那就是只要相邻两项有正差值,那么就可以买入卖出,此时局部最优就是整体最优解,正儿八经的贪心算法。只需要遍历数组,比较前后的差值与0的关系就行。

var maxProfit = function(prices){
    let result=0
    for(let i=1;i<prices.length;i++){
        result+=Math.max(0,prices[i]-prices[i-1])
    }
    return result
}

还有一种变体,那么加入卖完股票后有一天的冷冻期呢?

这个·我就直接选择动态规划,分析可知,每一个天只会有三种状态。第一种状态是手上持有股票(用0表示),第二种状态是处于冷冻期(用1表示),第三种状态时处于冷冻期之外的非持有股票(用2表示)。所以,dp[i][0],dp[i][1],dp[i][2]分别代表三种状态下的最大利润。

分析状态方程可以知道:

dp[i][0] = Math.max(dp[i-1][0] , dp[i-1][2]-prices[i])

dp[i][1] =?dp[i-1][0] ,?prices[i]

dp[i][2] = Math.max(dp[i-1][2] ,?dp[i-1][1])

第三步就是确定初始状态:

dp[0][0] = -prices[0],dp[0][0] = 0,dp[0][0] = 0

上代码:

var maxProfit = function(prices) {
    let dp=new Array(prices.length).fill(0).map(item=>new Array(3).fill(0))
    dp[0][0]=-prices[0]
    dp[0][1]=0
    dp[0][2]=0
    for(let i=1;i<prices.length;i++){
        //持有股票
        dp[i][0]=Math.max(dp[i-1][0],dp[i-1][2]-prices[i])
        //处于冷冻期,不持有股票
        dp[i][1]=dp[i-1][0]+prices[i]
        //不处于冷冻期,不持有股票
        dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1])
    }
    return Math.max(dp[prices.length-1][1],dp[prices.length-1][2])
};

以上就是关于股票题目的js分享,有贪心,有动态规划,以及类似双指针(争取一次性遍历数组)的思想了。仔细品味还是别有一番韵味,那么现在就有一个问题,是不是所有的算法到头来可以总结出一个元算法?就像宇宙物理里面的大一统理论呢?有待探索。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-04 13:05:02  更:2021-10-04 13:06:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:33:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码