leetcode-每日一题2022.3.4 子数组范围和

题目

力扣

思路一 枚举

枚举所有起点和终点,计算最大值到最小值的差,并添加到结果中。

代码一

class Solution {
public:
    long long subArrayRanges(vector<int>& nums) {
        long long ans = 0;
        int n = nums.size();
        for(int i = 0; i < n; i++){
            int minn = nums[i], maxx = nums[i];
            for(int j = i + 1; j < n; j++){
                minn = min(minn, nums[j]);
                maxx = max(maxx, nums[j]);
                ans += maxx - minn;
            }
        }
        return ans;
    }
};

思路二 单调栈

假设有m个区间,最终的表达式为m个等式max-min之和。用min数组和max数组存储每个数作为区间最小值和最大值的次数k1和k2,那么结果就是(k2-k1)*nums[i]为nums[i]对于最终答案的贡献。统计每个nums[i]称为区间最值的次数:例如找到nums[i]作为区间最大值的次数,找到nums[i]左右最近一个不满足小于等于nums[i]的位置,记为p和q。此时区间左端点共有i-p个选择,右端点共有q-i个选择,那么区间个数为(i-p)*(q-i)个。

代码二

class Solution {
public:
    long long subArrayRanges(vector<int>& nums) {
        int n = nums.size();
        long long ans = 0;
        vector<long> minn = getCnt(nums,true), maxx = getCnt(nums,false);
        for(int i = 0; i < n; i++)
            ans += (maxx[i] - minn[i]) * nums[i];
        return ans;
    }
    vector<long> getCnt(vector<int>& nums, bool isMin){
        int n = nums.size();
        vector<int> a(n), b(n);
        stack<int> s;
        for(int i = 0; i < n; i++){
            while(!s.empty() && (isMin ? nums[i] <= nums[s.top()] : nums[i] >= nums[s.top()]))
            s.pop();
            a[i] = s.empty() ? -1 : s.top();
            s.push(i);
        }
        while(!s.empty()) s.pop();
        for(int i = n - 1; i >= 0; i--){
            while(!s.empty() && (isMin ? nums[i] < nums[s.top()] : nums[i] > nums[s.top()]))
            s.pop();
            b[i] = s.empty() ? n : s.top();
            s.push(i);
        }
        vector<long> ans(n);
        for(int i = 0; i < n; i++)
            ans[i] = (i - a[i]) * (b[i] - i);
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值