目录
题目描述:
- 给你一个整数数组 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.手里没有股票;
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.在递增区间的结束位置卖掉,此时 我们的利润是最大的。
利润 = (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)
题目描述:
- 在一个平衡字符串 中,'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 是一个平衡字符串
贪心的本质就是将原问题拆成很多子问题,分而治之的思想。所以我们可以用一个变量 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)
谢谢观看!!