leetcode 维护前后缀最大最小值,前后缀分解

找出满足差值条件的下标 II()

给你一个下标从\(0\)开始、长度为\(n\)的整数数组\(nums\),以及整数\(indexDifference\)和整数\(valueDifference\)

你的任务是从范围\([0, n - 1]\)内找出\(2\)个满足下述所有条件的下标\(i\)\(j\)
\(abs(i - j) >= indexDifference\)\(abs(nums[i] - nums[j]) >= valueDifference\)
返回整数数组\(answer\)。如果存在满足题目要求的两个下标,则\(answer = [i, j]\);否则,\(answer = [-1, -1]\)。如果存在多组可供选择的下标对,只需要返回其中任意一组即可。

注意:\(i\)\(j\)可能 相等 。

示例 1:
输入:nums = [5,1,4,1], indexDifference = 2, valueDifference = 4
输出:[0,3]
解释:在示例中,可以选择 i = 0 和 j = 3 。
abs(0 - 3) >= 2 且 abs(nums[0] - nums[3]) >= 4 。
因此,[0,3] 是一个符合题目要求的答案。
[3,0] 也是符合题目要求的答案。

示例 2:
输入:nums = [2,1], indexDifference = 0, valueDifference = 0
输出:[0,0]
解释:
在示例中,可以选择 i = 0 和 j = 0 。
abs(0 - 0) >= 0 且 abs(nums[0] - nums[0]) >= 0 。
因此,[0,0] 是一个符合题目要求的答案。
[0,1]、[1,0] 和 [1,1] 也是符合题目要求的答案。

示例 3:
输入:nums = [1,2,3], indexDifference = 2, valueDifference = 4
输出:[-1,-1]
解释:在示例中,可以证明无法找出 2 个满足所有条件的下标。
因此,返回 [-1,-1] 。

提示:

\(1 <= n == nums.length <= 10^5\)
\(0 <= nums[i] <= 10^9\)
\(0 <= indexDifference <= 10^5\)
\(0 <= valueDifference <= 10^9\)

因为这个是返回任意一组就行,所以我们只需要维护前缀的最小最大值就行,如果前缀的最小值,最大值都不满足条件的话,那么这个一定不满足

class Solution {
public:
    vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
        //0 1 2 3
        //5 1 4 1
        int max_idx = 0, min_idx = 0;
        for(int j=indexDifference;j<nums.size();j++){
            int i=j-indexDifference;
            if(nums[i]>nums[max_idx]){
                max_idx=i;
            }
            else if(nums[i]<nums[min_idx]){
                min_idx=i;
            }
            if(nums[max_idx]-nums[j]>=valueDifference){
                return {max_idx,j};
            }
            if(nums[j]-nums[min_idx]>=valueDifference){
                return {min_idx,j};
            }
        }
        return {-1,-1};

    }
};

元素和最小的山形三元组 II

https://leetcode.cn/problems/minimum-sum-of-mountain-triplets-ii/description/
给你一个下标从\(0\)开始的整数数组\(nums\)
如果下标三元组 (i, j, k) 满足下述全部条件,则认为它是一个 山形三元组 :\(i < j < k\)
\(nums[i] < nums[j] 且 nums[k] < nums[j]\)
请你找出\(nums\)中 元素和最小 的山形三元组,并返回其 元素和 。如果不存在满足条件的三元组,返回 -1 。

示例 1:
输入:nums = [8,6,1,5,3]
输出:9
解释:三元组 (2, 3, 4) 是一个元素和等于 9 的山形三元组,因为:-2 < 3 < 4

  • nums[2] < nums[3] 且 nums[4] < nums[3]
    这个三元组的元素和等于 nums[2] + nums[3] + nums[4] = 9 。可以证明不存在元素和小于 9 的山形三元组。

示例 2:
输入:nums = [5,4,8,7,10,2]
输出:13
解释:三元组 (1, 3, 5) 是一个元素和等于 13 的山形三元组,因为: - 1 < 3 < 5

  • nums[1] < nums[3] 且 nums[5] < nums[3]
    这个三元组的元素和等于 nums[1] + nums[3] + nums[5] = 13 。可以证明不存在元素和小于 13 的山形三元组。

示例 3:
输入:nums = [6,5,4,3,4,5]
输出:-1
解释:可以证明 nums 中不存在山形三元组。

提示:
\(3 <= nums.length <= 10^5\)
\(1 <= nums[i] <= 10^8\)

这个题也是前后缀分解的题目,首先我们枚举j,因为他要找最小值,所以我们只需要找j之前的最小值和j之后的最小值就行,所以我们可以维护min1[i]代表这个前i个中最小值,然后维护一个min2[i]代表这个i到n的最小值

class Solution {
public:
    int minimumSum(vector<int>& nums) {
        int n=nums.size();
        int min1[n+3];
        int min2[n+3];
        for(int i=0;i<n+1;i++){
            min1[i]=1e9;
            min2[i]=1e9;
        }
        min1[0]=nums[0];
        for(int i=1;i<n;i++){
            min1[i]=min(min1[i-1],nums[i]);
        }
        for(int i=n-1;i>=0;i--){
            min2[i]=min(min2[i+1],nums[i]);
        }
        for(int i=0;i<n;i++){
            cout<<min1[i]<<" "<<min2[i]<<endl;
        }
        int ans=1e9;
        for(int i=1;i<n-1;i++){
            if(nums[i]>min1[i-1]&&nums[i]>min2[i+1]){
                ans=min(ans,nums[i]+min1[i-1]+min2[i+1]);
            }
        }
        if(ans==1e9){
            return -1;
        }
        else{
            return ans;
        }
    }
};
posted @ 2023-12-01 17:55  lipu123  阅读(62)  评论(0)    收藏  举报