每日一题,长度为 K 的子数组的能量值 II

给你一个长度为 n 的整数数组 nums 和一个正整数 k 。

一个数组的 能量值 定义为:

  • 如果 所有 元素都是依次 连续 且 上升 的,那么能量值为 最大 的元素。
  • 否则为 -1 。

你需要求出 nums 中所有长度为 k 的 

子数组

 的能量值。

请你返回一个长度为 n - k + 1 的整数数组 results ,其中 results[i] 是子数组 nums[i..(i + k - 1)] 的能量值。

示例 1:

输入:nums = [1,2,3,4,3,2,5], k = 3

输出:[3,4,-1,-1,-1]

解释:

nums 中总共有 5 个长度为 3 的子数组:

  • [1, 2, 3] 中最大元素为 3 。
  • [2, 3, 4] 中最大元素为 4 。
  • [3, 4, 3] 中元素 不是 连续的。
  • [4, 3, 2] 中元素 不是 上升的。
  • [3, 2, 5] 中元素 不是 连续的。

示例 2:

输入:nums = [2,2,2,2,2], k = 4

输出:[-1,-1]

示例 3:

输入:nums = [3,2,3,2,3,2], k = 2

输出:[-1,3,-1,3,-1]

提示:

  • 1 <= n == nums.length <= 105
  • 1 <= nums[i] <= 106
  • 1 <= k <= n

题目解读

这道题的核心在于判断一个给定的子数组是否满足“所有元素都是依次连续且上升”的条件。如果满足,则该子数组的能量值为其最大元素;如果不满足,则能量值为-1。我们可以用滑动窗口的方法来解决这个问题,这样可以有效地处理每个长度为k的子数组,并检查它们是否满足条件。

解决方案步骤:

  1. 初始化结果数组:创建一个长度为 n - k + 1 的结果数组 results,用于存储每个长度为 k 的子数组的能量值。

  2. 滑动窗口检查

    • 对于每个可能的起始位置 i(从 0 到 n - k),我们考虑子数组 nums[i:i+k]
    • 检查这个子数组是否满足“所有元素都是依次连续且上升”的条件。可以通过以下方式实现:
      • 遍历子数组中的相邻元素对 (nums[j], nums[j+1]),确保对于所有的 j(从 i 到 i + k - 2),都有 nums[j] + 1 == nums[j + 1]
      • 如果上述条件成立,则该子数组满足条件,其能量值即为子数组的最大值。
      • 否则,该子数组不满足条件,能量值为 -1
  3. 优化检查过程

    • 使用一个双端队列(Deque)来维护当前窗口内的最大值,从而在常数时间内获取最大值。
    • 使用双端队列来保持窗口内元素的单调递减顺序,这样队列的前端始终是当前窗口的最大值。

 代码实现

var resultsArray = function(nums, k) {
    
    const n = nums.length;  // 获取数组的长度
    let cnt = 0;  // 计数器,用于记录当前连续上升序列的长度
    const ans = new Array(n - k + 1).fill(-1);  // 初始化结果数组,长度为 n - k + 1,默认值为 -1

    for (let i = 0; i < n; i++) {
        // 如果是第一个元素,或者当前元素与前一个元素不是连续上升的,则重置计数器为 1
        // 否则,增加计数器
        cnt = (i === 0 || nums[i] - nums[i - 1] !== 1) ? 1 : cnt + 1;

        // 如果当前连续上升序列的长度达到了 k
        if (cnt >= k) {
            // 将当前元素作为能量值存入结果数组中
            // 结果数组的索引为 i - k + 1,因为这是当前子数组的起始位置
            ans[i - k + 1] = nums[i];
        }
    }

    return ans;  // 返回结果数组

}

复杂度分析

  • 时间复杂度:O(n),n 表示给定数组的长度。只需遍历一遍数组即可。

  • 空间复杂度:O(1),除返回值外,不需要额外的空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值