Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 数组

  • 链表

  • 字符串

  • 二叉树

  • 动态规划

  • 深搜回溯

  • 数学贪心

  • 堆栈队列

    • 394.字符串解码
    • 32. 最长有效括号
    • 739. 每日温度
    • 1130. 叶值的最小代价生成树
    • 84. 柱状图中最大的矩形
    • 42.接雨水
    • 85. 最大矩形
    • 239.滑动窗口最大值
    • 6891. 机器人碰撞
    • 445. 两数相加 II
    • 2762. 不间断子数组
    • 6919. 使数组中的所有元素都等于零
    • 862. 和至少为 K 的最短子数组
      • 1.前缀和+单调队列
    • 1499. 满足不等式的最大值
    • 2856. 删除数对后的最小数组长度
    • 901. 股票价格跨度
    • 2034. 股票价格波动
    • 1488. 避免洪水泛滥
    • 2940. 找到 Alice 和 Bob 可以相遇的建筑
    • 2454. 下一个更大元素 IV
  • 前缀和

  • 算法设计

  • 位运算

  • WA

  • 算法
  • 堆栈队列
phan
2023-07-21
目录

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

# 862. 和至少为 K 的最短子数组 (opens new window)

# 1.前缀和+单调队列

分析:用相邻前缀和之差来记录每个子数组之和,即便如此,前缀和暴力搜索的时间复杂度还是O(n平方)。因此使用单调队列来优化时间复杂度,这里单调的意思不仅队列保存的索引是递增的,同时索引对应的前缀和也是递增的。这里假设队首到队尾依次递减:

  • 优化1:如果当前位置 i 与队尾元素 j 的前缀和之差大于等于k,那么队尾元素直接出队列。因为在 i 后面若存在m(m>i) 也满足与j的前缀和之差不小于k,得到的数组长度 m-j 肯定比 i-j 小。因此pre[j]只有第一次计算的结果可能是最小子数组,后面就没有用了。
  • 优化2:如果当前位置 i 比队首位置 j 的前缀和大,那么队首元素直接出队列。因为如果在当前位置 i 之后存在m可以构成[j , m]的子数组,那么显然[i, m]也满足条件,并且子数组长度比前面队首元素构成的还要小。因此队列中比当前索引对应前缀和大的都需要移除队列。

这里单调队列保存是所有能够与当前位置 i (作为右边界)构成子数组的左边界索引。分析到这就很明了,滑动窗口或者双指针之所以做不了,是因为虽然左指针移动可以模拟上面的优化1,但是优化2仅使用两个指针做不到。

✨子数组和问题要想到转化为前缀和之差,并且创建时可以多开辟一个位置,将0作为哨兵节点,从而不需要单独考虑前缀和直接作为子数组和的情况。

✨无论是单调栈还是单调队列,核心原则都可以分为以下几个步:①将每个元素都入队/栈。②当前数据结构是否存在无用的/不会对最终结果产生印象/不会贡献其中一种可能答案的元素,那么就需要及时移除这些没有贡献的元素。

class Solution {
    public int shortestSubarray(int[] nums, int k) {
        long[] pre=new long[nums.length+1];
        for(int i=0;i<nums.length;i++){
            //设置一个哨兵元素0:表示当前子树组取的前缀和
            pre[i+1]=pre[i]+nums[i];
        }
        int res=Integer.MAX_VALUE;
        Deque<Integer> queue=new LinkedList<>();
        queue.offerLast(0);
        for(int i=1;i<nums.length+1;i++){
            while(!queue.isEmpty()&&pre[i]-pre[queue.peekLast()]>=k){
                res=Math.min(res,i-queue.pollLast());
            }
            while(!queue.isEmpty()&&pre[queue.peekFirst()]>=pre[i]) queue.pollFirst();
            queue.offerFirst(i);
        }
        if(res==Integer.MAX_VALUE) return -1;
        return res;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
编辑 (opens new window)
#Leetcode#堆栈队列#前缀和
上次更新: 2023/12/15, 15:49:57
6919. 使数组中的所有元素都等于零
1499. 满足不等式的最大值

← 6919. 使数组中的所有元素都等于零 1499. 满足不等式的最大值→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式