LeetCode862. Shortest Subarray with Sum at Least K
Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K.
If there is no non-empty subarray with sum at least K, return -1.
Example 1:
Input: A = [1], K = 1
Output: 1
Example 2:
Input: A = [1,2], K = 4
Output: -1
Example 3:
Input: A = [2,-1,2], K = 3
Output: 3
Note:
1 <= A.length <= 50000-10 ^ 5 <= A[i] <= 10 ^ 51 <= K <= 10 ^ 9
思路
本来以为用dp来做,看了下答案,解法中并没有。使用的解法是滑动窗口,将问题重新定义为和A的前缀和有关,定义
P[i] = A[0] + A[1] + ... + A[i-1]
我们想要求的便是最小的 y-x,y>x 并且P[y] - P[x] >= K
Motivated by that equation, let opt(y) be the largest x such that P[x] <= P[y] - K. We need two key observations:
If
x1 < x2andP[x2] <= P[x1], thenopt(y)can never bex1, as ifP[x1] <= P[y] - K, thenP[x2] <= P[x1] <= P[y] - Kbuty - x2is smaller. This implies that our candidatesxforopt(y)will have increasing values ofP[x].If
opt(y1) = x, then we do not need to consider thisxagain. For if we find somey2 > y1withopt(y2) = x, then it represents an answer ofy2 - xwhich is worse (larger) thany1 - x.
opt(y)是使得当 P[x] <= P[y] - K 时 x 能取到的最大值。
1. 如果有 x1<x2 并且 P[x2]<=P[x1],那么opt(y)一定不是 x1,因为如果有P[x1] <= P[y] - K,那么 P[x2] <= P[x1] <= P[y] - K,但是 y - x2 is smaller。这表明对于opt(y)的候选x应该是在使P(x)递增的区间去找。要注意这里的P[x1]指的是从0到X1的数组元素之和,不是单单指一个x1位置上元素的值。
2. 如果opt(y1)=x, 那么不需要再次考虑x。因为如果我们找到某些y2>y1并且opt(y2)=x,那么这表明这个解答 y2-x 是比之前的解答 y1-x 是更坏的答案。
Calculate prefix sum B of list A.B[j] - B[i] represents the sum of subarray A[i] ~ A[j-1]
Deque d will keep indexes of increasing B[i].
For every B[i], we will compare B[i] - B[d[0]] with K.
    public int shortestSubarray(int[] A, int K) {
        int N = A.length, res = N + 1;
        int[] B = new int[N + 1];
   // 下面利用数组A重新构造了数组B,满足B[i+1]-B[j]=A[i]+A[i-1].....+A[j]
        for (int i = 0; i < N; i++) B[i + 1] = B[i] + A[i];
        Deque<Integer> d = new ArrayDeque<>();
        for (int i = 0; i < N + 1; i++) {  
            while (d.size() > 0 && B[i] - B[d.getFirst()] >=  K)
                res = Math.min(res, i - d.pollFirst()); // 双端队列存的是索引
            while (d.size() > 0 && B[i] <= B[d.getLast()]) d.pollLast(); // Deque d keep indexes of increasing B[i]
            d.addLast(i);
        }
        return res <= N ? res : -1;
    }
上面的出入队列顺序是这样的:首先对于每个索引i,对应的是B[i],将这个索引作为y位置来考虑,因为双端队列保持的索引是的B[i]是递增的,为了从最大处逼近K,我们从队头依次取索引出来计算:
B[i] - B[d.getFirst()]
如果比K大,那么则要找这其中距离索引i最近的那一个:
res = Math.min(res, i - d.pollFirst());
然后是队列要keep indexes of increasing B[i],索引判断当前的B[i]是否大于队列尾部的索引处的
B[i] <= B[d.getLast()
如果不能构成递增,根据之前的分析,当前y所在的位置i的最优解opt(y)一定不会是在前面递增的部分取,所以队列要从后往前一个个弹出队尾直至能和B[i]构成递增序列。
LeetCode862. Shortest Subarray with Sum at Least K的更多相关文章
- 862. Shortest Subarray with Sum at Least K
		
Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there ...
 - [Swift]LeetCode862. 和至少为 K 的最短子数组 | Shortest Subarray with Sum at Least K
		
Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there ...
 - [LeetCode] 862. Shortest Subarray with Sum at Least K 和至少为K的最短子数组
		
Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K. If there ...
 - 【LeetCode】862. Shortest Subarray with Sum at Least K 解题报告(C++)
		
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 队列 日期 题目地址:https://leetcod ...
 - leetcode 862 shorest subarray with sum at least K
		
https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ 首先回顾一下求max子数组的值的方法是:记录一个前缀min值, ...
 - array / matrix subarray/submatrix sum
		
Maximal Subarray Sum : O(n) scan-and-update dynamic programming, https://en.wikipedia.org/wiki/Maxim ...
 - 【LeetCode】1099. Two Sum Less Than K 解题报告(C++)
		
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 日期 题目地址:https://leetco ...
 - LeetCode 1099. Two Sum Less Than K
		
原题链接在这里:https://leetcode.com/problems/two-sum-less-than-k/ 题目: Given an array A of integers and inte ...
 - [LeetCode] Partition to K Equal Sum Subsets 分割K个等和的子集
		
Given an array of integers nums and a positive integer k, find whether it's possible to divide this ...
 
随机推荐
- 安装redis环境
			
1 安装redis至 /home/www/redis目录下 [root@cuijian www]# tar zxf redis-2.8.13.tar.gz [root@cuijian www]# cd ...
 - Linux下chkconfig命令详解--(启动或停止)和查询系统服务的运行级信息
			
chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--ad ...
 - 框架----Django之ModelForm组件
			
ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信 ...
 - android ndk 编译的时候指令集的选取
			
android ndk在编译的时候默认生成的是thumb指令(拇指)不是arm(手臂)指令,但是有时候在看反汇编的时候,不太熟悉thumb指令或者说thumb指令看起来更费劲,需要生成arm指令,这个 ...
 - 【cdq分治】【CF1093E】 Intersection of Permutations
			
传送门 果然前两天写完咕咕咕那个题的题解以后博客就开始咕咕咕了-- Description 给定整数 \(n\) 和两个 \(1~\sim~n\) 的排列 \(A,B\). \(m\) 个操作,操作有 ...
 - MySQL自定义函数、触发器、存储过程
			
存储过程 概念 存储过程,是一个数据库对象,类似一个函数. 在存储过程中可以使用SQL中的绝大部分内容,并且可以加入编程语言的特性(循环判断分支). 编写好存储过程之后,可以在客户端调用存储过程,存储 ...
 - 04-树5. File Transfer--并查集
			
对于一个集合常见的操作有:判断一个元素是否属于一个集合:合并两个集合等等.而并查集是处理一些不相交集合(Disjoint Sets)的合并及查询问题的有利工具. 并查集是利用树结构实现的.一个集合用一 ...
 - Java的StringAPI的小练习
			
//-------------String类-------------- //求两个字符串的最大相同子串 /* 思路: 1.找出较短的那个字符串 2.找出短串的所有子串,使用contains函数判断是 ...
 - 封装-python
			
六 封装 从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小猫,小狗,小王八,还有alex一起装进麻袋,然后把麻袋封上口子.但其实这种理解相当片面 首先我们要了解 回到顶部 6.1 要封装什么 你 ...
 - NOIP模拟赛10
			
T1 [HAOI2010]软件安装 https://daniu.luogu.org/problem/show?pid=2515 树上背包,如果有i必须有j,j作为i的父节点 O(nm²) #inclu ...