LeetCode每日一题之3255. 长度为 K 的子数组的能量值 Ⅱ

解题思路

相较于昨天的每日一题,这道题将数据范围和数组长度扩大了,但是O(n)的时间复杂度无所畏惧。根据题意可知,我们需要找到长度为 k 且满足连续上升的子数组中的最大元素,对于一个长度为n的数组而言,有n-k+1个这样的数组,且是从左往右 “滑动” 的,我们将这样一个长度为k的连续数组称之为窗口。那么就只需要判断每个窗口的是否满足连续上升,具体而言,判断长度为k的窗口是否存在k-1个连续上升对(例如[ 2,3] 是一个连续上升对)。那么是否需要对每个窗口单独遍历进行判断呢?当然不需要这么做,我们可以使用滑动窗口机制,使用一个变量upk记录每个窗口的连续上升对。首先我们对第一个窗口进行遍历,统计连续上升对的数量并保存在upk中;对于剩下的n-k个窗口,我们将窗口右滑一步,并判断:

  • 新加进来的元素(窗口最右端)是否和前一个元素构成连续上升对?
    • 如果是,说明窗口增加一个连续上升对,再判断窗口最左端的元素是否和前一个元素构成构成连续上升对?
      • 如果是,说明窗口又减少了一个连续上升对,upk值保持不变;
      • 如果不是,那么窗口总体是增加一个连续上升对,upk值加一;
    • 如果不是,说明窗口的连续上升对没有增加,再判断窗口最左端的元素是否和前一个元素构成构成连续上升对?
      • 如果是,说明窗口减少了一个连续上升对,upk值减一;
      • 如果不是,那么窗口的连续上升对数量不变,upk不做修改。

对于每个窗口的upk值进行判断,若其值为k-1,那么将窗口最右边的元素插入返回数组中,否则将 -1插入返回数组中。

示例代码

class Solution {
public:
    vector<int> resultsArray(vector<int>& nums, int k) {
        vector<int> ans;
        int n = nums.size();
        int upk = 0;
        // 统计第一个窗口
        for(int i = 1; i < k; i++){
            if(nums[i] - nums[i-1] == 1) upk++;
        }
        if(upk == k-1) ans.push_back(nums[k-1]);
        else ans.push_back(-1);
        for(int i = k; i < n; i++){
            // 判断窗口的连续上升对变化
            if((nums[i] - nums[i-1] == 1) && (nums[i-k+1] - nums[i-k] != 1)){
                upk++;
            }
            else if((nums[i] - nums[i-1] != 1) && (nums[i-k+1] - nums[i-k] == 1)){
                upk--;
            }
            if(upk == k-1) ans.push_back(nums[i]);
            else ans.push_back(-1);
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值