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

目录

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)


谢谢观看!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Master_hl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值