当前位置: 首页 > news >正文

贪心算法 - 买卖股票的最佳时机|| + 分割平衡字符串

目录

1.买卖股票的最佳时机||

1.1 解题思路1:动态规划

1.2 解题思路2:贪心

2.分割平衡字符串

2.1 解题思路 - 贪心


1.买卖股票的最佳时机||

题目描述:

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候最多只能持有一股股票。
你也可以先购买,然后在同一天出售。返回你能获得的最大利润 。

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 
这笔交易所能获得利润 = 5 - 1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 
这笔交易所能获得利润 = 6 - 3 = 3 。
    总利润为 4 + 3 = 7 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 
这笔交易所能获得利润 = 5 - 1 = 4 。
     总利润为 4 。

提示:

。1 <= prices.length <= 3 * 104
。0 <= prices[i] <= 104

🍁题目解析

从题目中可以明确,任何时候,我们手里最多可以持有一股股票,我们可以在当天卖掉,也可以过几天再卖。我们的最终要求就是要通过不断对比今天和昨天的股票,然后选择最佳时机买卖股票,从而获得最大利润并返回。

1.1 解题思路1:动态规划

因为不能同时持有两股股票,所以每天交易结束后,我们持有的股票状态就只有两种:

1.手里没有股票;

2.手里持有一股股票。

因此我们就可以讨论这两种情况下每天交易完成之后,我们能获得的最大利润是多少。由于每一天的利润只和前一天有关,于是得出:

🍃1.第 i 天交易完之后,手里没有股票的最大利润

dp0 [i] = max( dp0 [i - 1], dp1 [i - 1] + prices [i] )

 

 🍃2.第 i 天交易完成之后,手里持有一股股票的最大利润

dp1 [i] = max(dp0 [i - 1] - prices [i], dp1 [i - 1])

所以我们只要从前往后依次计算状态即可。由于全部交易结束后,持有股票的利润一定低于不持有股票的利润,所以最终返回 dp0.

代码示例

    public int maxProfit(int[] prices) {
        // 第一天没买股票
        int dp0 = 0;
        // 第一天买了股票
        int dp1 = -prices[0];
        // 分情况讨论
        for(int i = 1; i < prices.length; i++) {
            // 1.第 i 天交易完之后,手里没有股票的最大利润
            dp0 = Math.max(dp0 , dp1 + prices[i]);
            // 2.第 i 天交易完成之后,手里持有一股股票的最大利润
            dp1 = Math.max(dp1,dp0 - prices[i]);
        }
        return dp0;
    }

复杂度分析

时间复杂度:O(n),只遍历一遍数组。

空间复杂度:此处做了空间优化,只用到了常数个空间。

1.2 解题思路2:贪心

贪心的本质就是将原问题拆成很多子问题,分而治之的思想。所以我们可以划区间来判断,什么时候入股,什么时候卖掉。

🍃1.当出现递增区间的时候,我们从第一个递增的位置开始入股;

🍃2.在递增区间的结束位置卖掉,此时 我们的利润是最大的。

利润 = (5 - 1)+ (6 - 3)= 7

代码示例

    public int maxProfit(int[] prices) {
        int profit = 0;
        for(int i = 0; i < prices.length - 1; i++) {
            if(prices[i] < prices[i + 1]) {
                // 将递增区间的利润全部加起来就是最大利润
                profit += (prices[i + 1] - prices[i]);
            }
        }
        return profit;
    }

复杂度分析

时间复杂度:O(n),只遍历一遍数组

空间复杂度:O(1)

2.分割平衡字符串

题目描述:

在一个平衡字符串 中,'L' 和 'R' 字符的数量是相同的。
给你一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。
注意:分割得到的每个字符串都必须是平衡字符串,且分割得到的平衡字符串是原平衡字符串的连续子串。
返回可以通过分割得到的平衡字符串的 最大数量 。

示例 1:

输入:s = "RLRRLLRLRL"
输出:4
解释:s 可以分割为 "RL"、"RRLL"、"RL"、"RL" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。

示例 2:

输入:s = "RLLLLRRRLR"
输出:3
解释:s 可以分割为 "RL"、"LLLRRR"、"LR" ,每个子字符串中都包含相同数量的 'L' 和 'R' 。

提示:

。1 <= s.length <= 1000
。s[i] = 'L' 或 'R'
。s 是一个平衡字符串

2.1 解题思路 - 贪心

贪心的本质就是将原问题拆成很多子问题,分而治之的思想。所以我们可以用一个变量 balance 从左到右依次找能被分割的子字符串。

🍃1.遇到 "L",balance += 1;

🍃2.遇到 "R",balance -= 1;

🍃3.当 balance == 0 的时候,说明这个子字符串是一串平衡字符串,于是而已通过变量 count 来统计。

代码示例

    public static int balancedStringSplit(String s) {
        // 平衡变量,数据达到平衡,就分割
        int balance = 0;
        // 统计分割出来的平衡字符串个数
        int count = 0;
        // 规定遇到 "L" 就 + 1,遇到 "R" 就 - 1
        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == 'L') {
                balance += 1;
            } else {
                balance -= 1;
            }
            // 平衡条件
            if(balance == 0) {
                count++;
            }
        }
        return count;
    }

复杂度分析

时间复杂度:O(n),只遍历一遍字符串

空间复杂度:O(1)


谢谢观看!!

相关文章:

  • ActiveReports.NET 16.2RPX 部分报告的完全支持
  • 专业英语第八章Communications and Networks测试题
  • 【Linux操作系统】-- 多线程(三)-- 线程池+单例模式+读写者模型
  • Pinia实操配置,Vuex的替代品
  • flume系列(一)部署示例及组件介绍
  • 【SpringBoot】静态资源导入探究
  • Redis cache-aside模型-分布式锁等问题研究
  • TypeScript 中 Type 和 Interface 有什么区别?
  • js中 scrollHeight、clientHeight、scrollTop的理解
  • Linux发布Spring Boot项目
  • 【面试题】sychronized
  • CodeForces 33B【贪心】【字符串】【最短路】
  • CF1114F Please, another Queries on Array?【线段树+欧拉函数】
  • vue02模板语法
  • 深度学习(pytorch)——神经网络完整模型训练套路及其注意事项
  • conda常用的命令
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • DOM的那些事
  • FineReport中如何实现自动滚屏效果
  • JavaScript类型识别
  • Just for fun——迅速写完快速排序
  • SpiderData 2019年2月23日 DApp数据排行榜
  • Web Storage相关
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 关于Java中分层中遇到的一些问题
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 后端_ThinkPHP5
  • 技术胖1-4季视频复习— (看视频笔记)
  • 前端之Sass/Scss实战笔记
  • 区块链将重新定义世界
  • 删除表内多余的重复数据
  • 深入浅出webpack学习(1)--核心概念
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 在Unity中实现一个简单的消息管理器
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 7行Python代码的人脸识别
  • Java总结 - String - 这篇请使劲喷我
  • Python 之网络式编程
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​Python 3 新特性:类型注解
  • ​马来语翻译中文去哪比较好?
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (39)STM32——FLASH闪存
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (SpringBoot)第七章:SpringBoot日志文件
  • (一)SpringBoot3---尚硅谷总结
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)程序员技术练级攻略
  • ../depcomp: line 571: exec: g++: not found
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .NET 设计模式—适配器模式(Adapter Pattern)