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. 1 <= A.length <= 50000
  2. -10 ^ 5 <= A[i] <= 10 ^ 5
  3. 1 <= 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 < x2 and P[x2] <= P[x1], then opt(y) can never be x1, as if P[x1] <= P[y] - K, then P[x2] <= P[x1] <= P[y] - K but y - x2 is smaller. This implies that our candidates x for opt(y) will have increasing values of P[x].

  • If opt(y1) = x, then we do not need to consider this x again. For if we find some y2 > y1 with opt(y2) = x, then it represents an answer of y2 - x which is worse (larger) than y1 - 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的更多相关文章

  1. 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 ...

  2. [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 ...

  3. [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 ...

  4. 【LeetCode】862. Shortest Subarray with Sum at Least K 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 队列 日期 题目地址:https://leetcod ...

  5. leetcode 862 shorest subarray with sum at least K

    https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/ 首先回顾一下求max子数组的值的方法是:记录一个前缀min值, ...

  6. array / matrix subarray/submatrix sum

    Maximal Subarray Sum : O(n) scan-and-update dynamic programming, https://en.wikipedia.org/wiki/Maxim ...

  7. 【LeetCode】1099. Two Sum Less Than K 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 日期 题目地址:https://leetco ...

  8. LeetCode 1099. Two Sum Less Than K

    原题链接在这里:https://leetcode.com/problems/two-sum-less-than-k/ 题目: Given an array A of integers and inte ...

  9. [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 ...

随机推荐

  1. x64 win64编译环境下ADO链接Access数据库的问题解决

    原文链接地址:https://blog.csdn.net/HW140701/article/details/71077579 Win32编译环境下,用ADO数据库连接Access数据库一般都不会报错, ...

  2. PHP 中的新语法 new static 是个啥意思?

    简单通俗的来说, self就是写在哪个类里面, 实际调用的就是这个类.所谓的后期静态绑定, static代表使用的这个类, 就是你在父类里写的static, 然后通过子类直接/间接用到了这个stati ...

  3. 【arc075F】Mirrored

    Portal --> arc075_f Solution ​  一开始抱着"我有信仰爆搜就可以过"的心态写了一个爆搜.. ​  但是因为..剪枝和枚举方式不够优秀愉快T掉了q ...

  4. dorado重置按钮事件

    // @Bind #btnReset.onClick!function(self, arg) { var subNo = view.get("#dsQueryCriteria"). ...

  5. OpenCV C++如何使RGB图像变为灰度图像

    http://m.blog.csdn.net/blog/u014395105/41308979 最近在研究如何用C++来处理图像,而不使用封装好的OpenCV代码,这样能够更好的了解OpenCV的内部 ...

  6. poj1006 生理周期

    生理周期 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 138947   Accepted: 44597 Descripti ...

  7. Linux iptables:规则原理和基础

    什么是iptables? iptables是Linux下功能强大的应用层防火墙工具,但了解其规则原理和基础后,配置起来也非常简单. 什么是Netfilter? 说到iptables必然提到Netfil ...

  8. Linux centos7下设置Tomcat开机自启动

    1,centos7 使用 systemctl 替换了 service命令 参考:redhat文档: https://access.redhat.com/documentation/en-US/Red_ ...

  9. 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes

    题目链接:http://codeforces.com/gym/101149/problem/G 题目大意:给你n对数字,为(a[i], b[i]),给你m对数字,为(w[i], c[i]).给n对数字 ...

  10. HDU6130 签到题 打表

    LINK 题意:给出一个描述自身的数列,求出第n项 思路:看了很久题目才看懂..每个值其实是描述一个分组中的个数,把两个数列对照一下就可以了,那么一个指针扫,同时向尾部加数,构造个数组就行了.其实很水 ...