每日一题:862. 和至少为 K 的最短子数组

196 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

862. 和至少为 K 的最短子数组

给你一个整数数组 nums 和一个整数 k ,找出 nums 中和至少为 k 的 最短非空子数组 ,并返回该子数组的长度。如果不存在这样的 子数组 ,返回 -1 。

子数组 是数组中 连续 的一部分。  

示例 1:

输入: nums = [1], k = 1
输出: 1

示例 2:

输入: nums = [1,2], k = 4
输出: -1

示例 3:

输入: nums = [2,-1,2], k = 3
输出: 3

提示:

  • 1 <= nums.length <= 105
  • -105 <= nums[i] <= 105
  • 1 <= k <= 109

暴力解法优化:剪枝

  • 在两层for循环的基础上进行剪枝。
    • 由于k>=1,所以任何连续子数组内一旦第一个数为负数,说明后面还需要一个正数对数组和进行调节。导致该数组不是最短的。
    • if(第一个数值为非正数,则舍弃该遍历,不为它找子数组求和。)
    • 在求和过程中,如果前缀和为非正数
      • 将它和第一个数值同样处理,舍弃后面的遍历,不再为它找子数组求和。
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
 var shortestSubarray = function(nums, k) {
    let count = nums.length;
    let min = count + 1;
    for (let i = 0; i < count; i++) {
        if (nums[i] <= 0) {
            continue;
        }
        if (nums[i] >= k) {
            return 1;
        }
        let total = nums[i];
        for (let j = i + 1; j < count && (j - i + 1) < min; j++) {
            total += nums[j];
            if (total <= 0) {
                break;
            }
            if (total >= k) {
                if (j - i + 1 < min) {
                    min = j - i + 1;
                } 
            }
        }
    }
    if (min === count + 1) {
        return -1;
    }
    return min;
};

前缀和+单调队列

  • 要获取前缀和 >= K, 则队列里的前缀和必须是递增的 否则两个前缀和的差值必为负数,而K是 >=1 的
  • 出现满足 >= k 的关系式子 则开始取 区间更接近 也就是说子数组长度更小的结果
  • 此时最左边的元素可以移掉了 原因是 下一个元素即使满足 差值 >= K 但是他和下一个元素
  • 之间的距离一定会比当前元素的距离要大。
var shortestSubarray = function(nums, k) {
    const n = nums.length;
    let sum:number[] = new Array(n+1);
    sum[0] = 0;
    for(let i=1; i<=n; i++){
        sum[i] = sum[i-1] + nums[i-1];
    }

    let q:number[] = [];
    let l = 0;
    let res = Infinity;
    for(let i=0; i<=n; i++){
        while(l<q.length && sum[i]-sum[q[l]]>=k){
            res = Math.min(res, i-q[l]);
            l++;
        }
        // maintain monotonic incremental stack
        while(q.length && sum[i]<sum[q[q.length-1]]){
            q.pop();
        }
        q.push(i);
    }
    return res === Infinity ? -1 : res;
};