代码随想录刷题|LeetCode 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II

news2024/11/26 17:22:44

目录

121. 买卖股票的最佳时机

思路

暴力解法

贪心算法

动态规划

买卖股票的最佳时机

贪心算法

动态规划

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

思路

分析递推公式

买卖股票的最佳时机II

贪心算法

动态规划


121. 买卖股票的最佳时机

题目链接:力扣

思路

暴力解法

        暴力解答会超出时长
        

        

贪心算法

        因为股票就买卖一次,贪心算法的想法是:取最左侧最小值,取最右侧的最大值,那么这个差值就是可以得到的最大利润

动态规划

        其实我们要做的是,就是两件事:
        在什么时候买入的时候最小
        在什么时候卖出的时候赚的最多

1、确定dp数组及其下标的含义

        dp[i][0] : 表示第 i 天持有股票所得最多现金的情况。一开始现金是0 ,如果买入就是负数
                      这里实际意义是: 保存买入的最小数
        dp[i][1]:表示第 i 天不持有股票所得最多现金
                      这里实际意义是:根据当前保存的最小买入数,保存当天卖出的话可获得的最大利润

2、确定递推公式

对于持有股票dp[i][0]:

  • 如果在 i - 1 天就持有了股票,那就不能再买了,这种状态就是dp[i - 1][0]
  • 如果要在 i 天买入,这种状态就是 -prices[i]
  • 所以这个就是代表,怎么买入才能话最少的钱,所以应该选其中的最大值
    因此 : dp[i][0] = Math.max( dp[i -1][0] , -prices[i] );

对于不持有股票dp[i][1]

  • 如果在 i - 1天已经卖出股票了,那就保持之前的状态,就是dp[i-1][1]
  • 如果前面没有卖出过,那就试试在 i 天卖出,这种状态就是:卖出的价格 - 前面买入的最小数,因此是:prices[ i ] - dp[i - 1][0]
  • 所以这个就是代表,当天价格 - 之前获得的最小买入,保存的是获得的利润,所以应该选取其中的最大值,因此:dp[i][1] = Math.max(dp[i -1][1], prices[i] - dp[i- 1][0]);

3、初始化dp数组

        从递推公式可以看出,我们是需要对dp[0][0]和dp[0][1]进行初始化的

        dp[0][0] 表示如果在 第0天买入股票后,手中的现金为:dp[0][0] = 0 - prices[0] = -prices[0]
        dp[0][1] 表示如果在 第0天卖出股票后,手中的现金为:dp[0][1] = 0

4、遍历顺序

        显然,是从前向后遍历

买卖股票的最佳时机

贪心算法

class Solution {
    public int maxProfit(int[] prices) {

        // 最小值
        int left = Integer.MAX_VALUE;
        // 结果
        int result = 0;

        for (int i = 0; i < prices.length; i++) {
            left = Math.min(left,prices[i]);
            result = Math.max(result,prices[i]-left);
        }

        return result;
    }
}

动态规划

版本一:使用二维数组

class Solution {
    public int maxProfit(int[] prices) {

        // 创建dp数组
        int[][] dp = new int[prices.length][2];

        // 初始化dp[]数组
        dp[0][0] = -prices[0];
        dp[0][1] = 0;

        // 进行动态推算
        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],prices[i] + dp[i-1][0]);  // 不断获取什么时候卖出的之后最大
        }

        return dp[prices.length-1][1];
    }
}

版本二:使用二维滚动数组

class Solution {
    public int maxProfit(int[] prices) {

        // 创建dp数组
        int[][] dp = new int[2][2];

        // 初始化dp[]数组
        dp[0][0] = -prices[0];
        dp[0][1] = 0;

        // 进行动态推算
        for (int i = 1; i < prices.length; i++) {
            dp[i % 2][0] = Math.max(dp[(i-1) % 2][0],-prices[i]);  // 将最小买入位保存了下来
            dp[i % 2][1] = Math.max(dp[(i-1) % 2][1],prices[i] + dp[(i-1) % 2][0]);  // 不断获取什么时候卖出的之后最大
        }

        return dp[(prices.length-1) % 2][1];
    }
}

版本三:使用一维数组

class Solution {
    public int maxProfit(int[] prices) {
        
        // 创建dp数组
        int[] dp = new int[2];

        // dp[0]保存最小买入数
        dp[0] = Integer.MAX_VALUE;
        // dp[i]保存当前卖出可获得的最大利润
        dp[1] = 0;

        for (int i = 0; i < prices.length; i++) {
            // 更新最小买入
            dp[0] = Math.min(dp[0],prices[i]);
            // 获取当前卖出可获取的利润
            dp[1] = Math.max(dp[1],prices[i]-dp[0]);
        }

        return dp[1];
    }
}

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

题目链接:力扣

思路

        这道题目在贪心算法的时候做过,再使用动态规划完成,与121题目的区别是可以买卖多次,买入前必须卖出

        和121除了递推公式,其他都是一样的

分析递推公式

dp数组的含义:

  • dp[i][0] 表示第 i 天持有股票所得现金,就是买入股票后手中的现金
  • dp[i][1] 表示第 i 天不持有股票所得的最多现金,就是卖出股票后手中的现金
  • 其实这两个,代表的都是手中有的现金数

怎么推导dp[i][0]:

  • 如果第 i-1 天持有股票,表示已经买入股票了,就不能再买入了,保持前面的状态就可以,也就是:dp[i - 1][0]
  • 如果第 i-1 天没有持有股票,表示可以买入股票了,那么就买入,手中的现金就是,dp[i - 1][1] - prices[i]

怎么推导dp[i][1]:

  • 如果第 i-1 天不持有股票了,那就不可以卖,那么就是保持现状,dp[i - 1][1]
  • 如果第 i-1 天持有股票,那就可以卖了,dp[i - 1][0] + prices[i]

买卖股票的最佳时机II

贪心算法

class Solution {
    public int maxProfit(int[] prices) {

        int result = 0;

        for (int i = 0; i + 1 < prices.length; i++) {
            int temp = prices[i + 1] - prices[i];
            if (temp > 0) {
                result += temp;
            }
        }

        return result;
    }
}

动态规划

版本一:使用二维数组

class Solution {
    public int maxProfit(int[] prices) {

        // 创建的dp[]数组
        int[][] dp = new int[prices.length][2];

        // 初始化dp数组
        dp[0][0] = -prices[0];
        dp[0][1] = 0;

        // 推导dp数组
        for (int i = 1; i < prices.length; i++) {
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]-prices[i]); // 这里与121的区别
            dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
        }

        return dp[prices.length - 1][1];
    }
}

版本二:使用滚动二维数组

class Solution {
    public int maxProfit(int[] prices) {

        // 创建的dp[]数组
        int[][] dp = new int[2][2];

        // 初始化dp数组
        dp[0][0] = -prices[0];
        dp[0][1] = 0;

        // 推导dp数组
        for (int i = 1; i < prices.length; i++) {
            dp[i % 2][0] = Math.max(dp[(i-1) % 2][0],dp[(i-1) % 2][1]-prices[i]);
            dp[i % 2][1] = Math.max(dp[(i-1) % 2][1],dp[(i-1) % 2][0]+prices[i]);
        }

        return dp[(prices.length - 1) % 2][1];
    }
}

版本三:使用一维数组

class Solution {
    public int maxProfit(int[] prices) {

        // 创建的dp[]数组
        int[] dp = new int[2];

        // 初始化dp数组
        dp[0] = Integer.MIN_VALUE; // 代表持有当前股票手中的现金
        dp[1] = 0;                 // 代表卖出卖出股票手中的现金

        // 推导dp数组
        for (int i = 0; i < prices.length; i++) {
            // 前一天是持有的情况
            dp[0] = Math.max(dp[0],dp[1] - prices[i]);
            dp[1] = Math.max(dp[1],dp[0] + prices[i]);
        }

        return dp[1];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/48155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

矩池云|GPU 分布式使用教程之 TensorFlow

GPU 分布式使用教程之 TensorFlow TensorFlow 提供了6种策略实现分布式计算&#xff0c;各个策略详情请参考官方文档。本文档使用 MirroredStrategy 实现单机多卡分布式&#xff0c;MultiWorkerMirroredStrategy 实现多机多卡分布式计算。 选择机器 单机多卡分布式&#xff1…

【MySQL进阶】多表连接的原理

【MySQL进阶】多表连接的原理 文章目录【MySQL进阶】多表连接的原理前言一&#xff1a;连接简介1&#xff1a;连接的本质2&#xff1a;连接过程简介二&#xff1a;连接的原理1&#xff1a;嵌套循环连接&#xff08;Nested-Loop Join&#xff09;2&#xff1a;使用索引加快连接速…

MySQL 8.*版本 修改root密码报错

1、mysql.sock报错 解决办法&#xff1a; 1、根据报错提示&#xff0c;是无法找到/tmp下面的mysql.sock。 2、全局搜索该文件&#xff1a;mysql.sock。 使用命令&#xff1a;find / -iname "mysql.sock" 为mysql.sock该文件创建软连接&#xff0c;命令如下&#x…

基于Java Web的传智播客crm企业管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

Redis企业版数据库如何支持实时金融服务?

一、数字化转型正在颠覆银行业和金融业 随着金融科技初创公司和互联网巨头利用前沿技术重塑客户对金融服务的预期&#xff0c;金融服务行业正在经历大规模的数字化颠覆。 对于非接触式支付、移动银行、信贷决策、欺诈检测等服务&#xff0c;金融业客户要求“实时体验”&#…

使用tinode架设自己的私有聊天服务

需求 众所周知的原因&#xff0c;使用公用的即时聊天工具并不安全&#xff0c;比如某企鹅家的"wei xin"&#xff0c;我们需要一个自己的安全的聊天工具&#xff0c;比如我们需要传递账号以及密码等&#xff1b; 方案1&#xff1a; 使用网页工具将文本加密&#xf…

一、【redux】redux简介 mini版求和Demo

文章目录1、学习文档2、redux是什么3、什么情况下需要使用redux4、redux工作流程5、redux的三个核心概念5.1、action5.2、reducer5.3、store6、redux的核心API6.1、createStore()6.2、store对象6.3、applyMiddleware()6.4、combineReducers()7、求和Demo&#xff08;纯react版&…

拖死项目的不是团队,可能是失败的管理

项目中的活动&#xff0c;归根结底是由人来完成的&#xff0c;如何发挥项目成员的能力&#xff0c;对于项目的成败起着至关重要的作用。如何充分地发挥团队成员的能力&#xff0c;对项目经理也是一个挑战。 在团队管理者我们会遇见这些难题&#xff1a; 1、团队凝聚力不足&a…

配置CentOS

一、启动虚拟机 1、登录虚拟机 出现[rootlocalhost]#提示符&#xff0c;表明登录成功 2、查看IP 命令&#xff1a; ip addr 3、是否ping通外网 命令&#xff1a;ping www.baidu.com 二、配置静态IP地址 1、修改网卡配置文件 命令&#xff1a;vi /etc/sysconfig/net…

UBoot怎么跳转到Kernel:uboot与linux的交界

不知道你是否有这种感觉&#xff0c;就是学习了一段时间Uboot&#xff0c;学习了一段时间kernel&#xff0c;也知道Uboot是引导程序。但是总是连不起来。 我为什么来的这样的感受是因为&#xff0c;我最近在学习安全相关的东西。但是这个安全的东西应用在kernel里面进行&#…

路径规划算法之刚体变换

目录 1 一般概念 1.1 基元的变换 1.2 一个参数化的变换族 2 2D变换 2.1 translation 2.2 rotation 2.3 Combining translation and rotation 3 3D变换 3.1 Yaw, pitch, and roll rotations 3.2 Determining yaw, pitch, and roll from a rotation matrix 3.3 The ho…

模拟电路设计(35)---几种脉宽调制型开关电路

Forward单端正激变换器 在buck变换器开关与负载之间插入隔离变压器&#xff0c;这种隔离型buck变换器叫做Forward单端正激变换器。如下图所示&#xff1a; Forward单端正激变换器 简单分析可知&#xff0c;滤波电感L在开关管关断期间&#xff0c;通过续流二极管为负载提供电流…

Android JNI编程并生成so库

这里写自定义目录标题Android JNI编程并生成so库Android Studio配置下载配置NDK配置NDK路径编写native方法和c文件编写配置文件生成so库使用so库Android JNI编程并生成so库 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编…

Python——字符串

1、再Python中&#xff0c;使用单引号或者双引号括起来的&#xff0c;就是字符串 2、字符串也可以使用六个单引号或者六个双引号括起来。 3、在Python3中&#xff0c;字符串分为两种类型&#xff0c;第一种是str&#xff0c;是unicode字符串&#xff0c;第二种是bytes&#x…

springboot酒店客房管理系统设计

随着我国市场经济的快速发展以及人们生活水平的不断提高&#xff0c;酒店&#xff0c;宾馆之间的竞争也越来越激烈&#xff0c;为了在这场竞争中取得显著的优势&#xff0c;就必须在管理上加以改善。在某种意义上&#xff0c;酒店客房方面的信息化已经成为现代化酒店的重要标志…

Python学习笔记第三十七天(NumPy 广播(Broadcast))

Python学习笔记第三十七天NumPy 广播(Broadcast)NumPy 广播(Broadcast) 广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式&#xff0c; 对数组的算术运算通常在相应的元素上进行。 如果两个数组 a 和 b 形状相同&#xff0c;即满足 a.shape b.shape&…

gurobi 基于python的gurobipy库使用,具有一维变量和二维变量的复杂模型求解

写在前面 可以参考下pulp和scip两篇的&#xff0c;比较详细&#xff0c;尤其pulp篇。举一反三&#xff0c;很好入门。 步骤 定义问题&#xff1a;m Model(name) 定义变量&#xff1a;x m.addVars(range(len), vtypeGRB.BINARY) 定义目标函数&#xff1a;m.setObjective&…

Springboot+ssm(Spring+SpringMVC+MyBatis)旧物置换网站

目 录 摘 要 I 目 录 III 第1章 概述 1 1.1 研究背景 1 1.2 研究现状 1 1.3 研究内容 2 第二章 开发技术介绍 2 2.1 系统开发平台 2 2.2 平台开发相关技术 3 2.2.1 B/S架构 3 2.2.2 Java技术介绍 4 2.2.3 mysql数据库介绍 4 2.2.4 …

【Electron】开发实战

文章目录第一章 征程第二章-主进程与渲染进程第三章-H5拖拽读取本地文件第四章-快捷键注册及复制粘贴第五章-渲染进程调用主进程模块第六章-菜单模块第七章-渲染进程与主进程间的通信第八章-渲染进程与渲染进程间的通信第九章-管理应用程序文件及url的加载方式第十章-系统对话框…

机械硬盘HDD

硬盘&#xff08;英语&#xff1a;Hard Disk Drive&#xff0c;缩写&#xff1a;HDD&#xff0c;有时为了与固态硬盘相区分称“机械硬盘”或“传统硬盘”&#xff09;是电脑上使用坚硬的旋转盘片为基础的非易失性存储器&#xff0c;它在平整的磁性表面存储和检索数字数据&#…