【小羊肖恩】从暴力到贪心:想清楚贪心的每一步,就可以顺序遍历啦~!
2023年10月1日 12:23
对于这个问题,数据范围是 $100$ 的情况,我们可以直接暴力枚举所有合法的 $(i, j, k)$ 三元组,看其值取最大即可。 注意要求如果是负值时,返回 $0$.
时间复杂度为 $\mathcal{O}(n^3)$.
具体代码如下——
###Python
class Solution:
def maximumTripletValue(self, nums: List[int]) -> int:
n = len(nums)
ans = 0
for k in range(n):
for j in range(k):
for i in range(j):
ans = max(ans, (nums[i] - nums[j]) * nums[k])
return ans
接下来我们思考如何处理 $n \leq 10^5$ 的情况。
首先,输出的数值最小为 $0$,同时数组中每个元素均为正数,因此,我们要让 (nums[i] - nums[j]) * nums[k]
最大,只需要对于固定的 $k$ 找到其前面 nums[i] - nums[j]
的最大值。
为了使得 nums[i] - nums[j]
尽可能大,我们需要对于固定的 j
找到其前面最大的 nums[i]
再将两者相减。
以上逻辑可见代码注释。
因此我们只需要维护三个东西:到当前位置的最大值,到当前位置为止最大的 nums[i] - nums[j]
,到当前位置为止最大的 (nums[i] - nums[j]) * nums[k]
. 而从上面的分析可以看出,这些都可以遍历过程中实现。
因此时间复杂度是 $\mathcal{O}(n)$ 的。
具体代码如下——
###Python
class Solution:
def maximumTripletValue(self, nums: List[int]) -> int:
# 当前最大值
curr_max = 0
# 当前最大的 nums[i] - nums[j]
curr_v = 0
# 当前最大的 (nums[i] - nums[j]) * nums[k]
ans = 0
n = len(nums)
for i in range(n):
# 答案的最大值根据最大的 nums[i] - nums[j] 和当前数值的乘积更新
ans = max(ans, nums[i] * curr_v)
# nums[i] - nums[j] 的最大值根据此前最大值减去当前数值更新
curr_v = max(curr_v, curr_max - nums[i])
# 更新前缀最大值
curr_max = max(curr_max, nums[i])
return ans