类似前缀和的 left min 和 right max,在求解买卖股票的最佳时机、递增的三元子序列比较有效
334. 递增的三元子序列
难度中等
给你一个整数数组 nums
,判断这个数组中是否存在长度为 3
的递增子序列。
如果存在这样的三元组下标 (i, j, k)
且满足 i < j < k
,使得 nums[i] < nums[j] < nums[k]
,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,4,5] 输出:true 解释:任何 i < j < k 的三元组都满足题意
示例 2:
输入:nums = [5,4,3,2,1] 输出:false 解释:不存在满足题意的三元组
示例 3:
输入:nums = [2,1,5,0,4,6] 输出:true 解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6
用dp做的话 n2复杂度,会用例超时:
dp[i] 表示第i个数小的元素的个数。 转移方程 if(nums[j] < nums[i]) dp[i] = max(dp[i],dp[j]+1) 如果直接两层for就超时了,最后一个测试用例过不去/。 链接:https://leetcode.cn/problems/increasing-triplet-subsequence/solution/dai-ma-jie-de-xiao-bai-javac-tan-xin-don-85ai/
类似前缀和的 left min 和 right max,用空间换时间。
class Solution: def increasingTriplet(self, nums: List[int]) -> bool: n = len(nums) min_vals = [0] * n # left min max_vals = [0] * n # right max min_vals[0] = nums[0] max_vals[n-1] = nums[n-1] for i in range(1, n): min_vals[i] = min(min_vals[i-1], nums[i]) max_vals[n-1-i] = max(max_vals[n-i], nums[n-1-i]) for i in range(n): if min_vals[i] < nums[i] < max_vals[i]: return True return False
另外还有一种技巧的解法,如下:
class Solution: def increasingTriplet(self, nums) -> bool: # ref: https://leetcode.cn/problems/increasing-triplet-subsequence/solution/c-xian-xing-shi-jian-fu-za-du-xiang-xi-jie-xi-da-b/ n = len(nums) small, mid = float('inf'), float('inf') for i in range(n): t = nums[i] if t <= small: small = t elif t <= mid: mid = t elif t > mid: return True return False
121. 买卖股票的最佳时机
难度简单
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
。
示例 1:
输入:[7,1,5,3,6,4] 输出:5 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
和上面那个题都可以使用一样的思路做!!!