LeetCode 2874. 有序三元组中的最大值 II

​​​​​​2874. 有序三元组中的最大值 II

给你一个下标从 0 开始的整数数组 nums 。

请你从所有满足 i < j < k 的下标三元组 (i, j, k) 中,找出并返回下标三元组的最大值。如果所有满足条件的三元组的值都是负数,则返回 0 。

下标三元组 (i, j, k) 的值等于 (nums[i] - nums[j]) * nums[k] 。

示例 1:

输入:nums = [12,6,1,2,7]
输出:77
解释:下标三元组 (0, 2, 4) 的值是 (nums[0] - nums[2]) * nums[4] = 77 。
可以证明不存在值大于 77 的有序下标三元组。

示例 2:

输入:nums = [1,10,3,4,19]
输出:133
解释:下标三元组 (1, 2, 4) 的值是 (nums[1] - nums[2]) * nums[4] = 133 。
可以证明不存在值大于 133 的有序下标三元组。 

示例 3:

输入:nums = [1,2,3]
输出:0
解释:唯一的下标三元组 (0, 1, 2) 的值是一个负数,(nums[0] - nums[1]) * nums[2] = -3 。因此,答案是 0 。

提示:

  • 3 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6

提示 1

Preprocess the prefix maximum array, prefix_max[i] = max(nums[0], nums[1], …, nums[i]) and the suffix maximum array, suffix_max[i] = max(nums[i], nums[i + 1], …, nums[n - 1]).


提示 2

For each index j, find two indices i and k such that i < j < k and (nums[i] - nums[j]) * nums[k] is the maximum, using the prefix and suffix maximum arrays.


提示 3

For index j, the maximum triplet value is (prefix_max[j - 1] - nums[j]) * suffix_max[j + 1].

解法1:枚举j

枚举 j,为了让 (nums[i]−nums[j])∗nums[k] 尽量大,我们需要知道 j 左侧元素的最大值,和 j 右侧元素的最大值。

也就是 nums 的前缀最大值 prefixMax 和后缀最大值 suffixMax,这都可以用递推预处理出来:

prefixMax[i]=max(prefixMax[i−1],nums[i])
suffixMax[i]=max(suffixMax[i+1],nums[i])
代码实现时,可以只预处理 suffixMax 数组,prefixMax 可以在计算答案的同时算出来。

Java版:

class Solution {
    public long maximumTripletValue(int[] nums) {
        int n = nums.length;
        int[] prefixMax = new int[n];
        int[] suffixMax = new int[n];
        prefixMax[0] = nums[0];
        suffixMax[n - 1] = nums[n - 1];
        for (int i = 1; i < n; i++) {
            prefixMax[i] = Math.max(prefixMax[i - 1], nums[i]);
        } 
        for (int i = n - 2; i >= 0; i--) {
            suffixMax[i] = Math.max(suffixMax[i + 1], nums[i]);
        }
        long ans = 0;
        // 0 <= i < j < k <= n - 1,所以j的范围为开区间(0,n-1)
        for (int j = 1; j < n - 1; j++) {
            ans = Math.max(ans, (long) (prefixMax[j - 1] - nums[j]) * suffixMax[j + 1] );
        }
        return ans;
    }
}

另一种写法:

class Solution {
    public long maximumTripletValue(int[] nums) {
        int n = nums.length;
        int[] suffixMax = new int[n];
        suffixMax[n - 1] = nums[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            suffixMax[i] = Math.max(suffixMax[i + 1], nums[i]);
        }
        int prefixMax = nums[0];
        long ans = 0;
        // 0 <= i < j < k <= n - 1,所以j的范围为开区间(0,n-1)
        for (int j = 1; j < n - 1; j++) {
            ans = Math.max(ans, (long) (prefixMax - nums[j]) * suffixMax[j + 1] );
            prefixMax = Math.max(prefixMax, nums[j]);
        }
        return ans;
    }
}

Python3版:

class Solution:
    def maximumTripletValue(self, nums: List[int]) -> int:
        n = len(nums)
        suffixMax = [0] * n
        suffixMax[n - 1] = nums[n - 1]
        for i in range(n - 2, -1, -1):
            suffixMax[i] = max(suffixMax[i + 1], nums[i])

        prefixMax = [0] * n
        prefixMax[0] = nums[0]
        for i in range(1, n):
            prefixMax[i] = max(prefixMax[i - 1], nums[i])

        ans = 0
        for j in range(1, n - 1):
            ans = max(ans, (prefixMax[j - 1] - nums[j]) * suffixMax[j + 1] )

        return ans
        

另一种写法:

class Solution:
    def maximumTripletValue(self, nums: List[int]) -> int:
        n = len(nums)
        suffixMax = [0] * n
        suffixMax[n - 1] = nums[n - 1]
        for i in range(n - 2, -1, -1):
            suffixMax[i] = max(suffixMax[i + 1], nums[i])

        prefixMax = nums[0]
        ans = 0
        for j in range(1, n - 1):
            ans = max(ans, (prefixMax - nums[j]) * suffixMax[j + 1] )
            prefixMax = max(prefixMax, nums[j])
        return ans
        
复杂度分析
  • 时间复杂度:O(n),其中 n 为 nums 的长度。
  • 空间复杂度:O(n)。

解法2: 枚举 k

枚举 k,我们需要知道 k 左边 nums[i]−nums[j] 的最大值。

我们可以在遍历的过程中,维护 nums[i] 的最大值 preMax,同时维护 preMax 减当前元素的最大值 maxDiff,这就是 k 左边 nums[i]−nums[j] 的最大值。

Java版:

class Solution {
    public long maximumTripletValue(int[] nums) {
        int n = nums.length;
        int preMax = Math.max(nums[0], nums[1]);
        int maxDiff = nums[0] - nums[1];
        long ans = 0;
        // 0 <= i < j < k <= n - 1,所以k的下标范围为闭区间[2, n - 1]
        for (int k = 2; k < n; k++) {
            ans = Math.max(ans, (long) maxDiff * nums[k]);
            maxDiff = Math.max(maxDiff, preMax - nums[k]);
            preMax = Math.max(preMax, nums[k]);
        }
        return ans;
    }
}

Python3版:

class Solution:
    def maximumTripletValue(self, nums: List[int]) -> int:
        preMax = max(nums[0], nums[1])
        maxDiff = nums[0] - nums[1]
        ans = 0
        for k in range(2, len(nums)):
            ans = max(ans, maxDiff * nums[k])
            maxDiff = max(maxDiff, preMax - nums[k])
            preMax = max(preMax, nums[k])
        return ans
复杂度分析
  • 时间复杂度:O(n),其中 n 为 nums 的长度。
  • 空间复杂度:O(1)。
  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值