LeetCode862. Shortest Subarray with Sum at Least K
Return the length of the shortest, non-empty, contiguous subarray of
Awith 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 ^ 5
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
xsuch that
P[x] <= P[y] - K. We need two key observations:
-
If
x1 < x2
andP[x2] <= P[x1]
, thenopt(y)
can never bex1
, as ifP[x1] <= P[y] - K
, thenP[x2] <= P[x1] <= P[y] - K
buty - x2
is smaller. This implies that our candidatesx
foropt(y)
will have increasing values ofP[x]
. -
If
opt(y1) = x
, then we do not need to consider thisx
again. For if we find somey2 > y1
withopt(y2) = x
, then it represents an answer ofy2 - x
which 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 - x2is 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
Bof list
A.
B[j] - B[i]represents the sum of subarray
A[i] ~ A[j-1]
Deque
dwill 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]构成递增序列。
- leetcode_[python/C++]_395_Longest Substring with At Least K Repeating Characters
- 【LeetCode】 395. Longest Substring with At Least K Repeating Characters
- Leetcode-395. Longest Substring with At Least K Repeating Characters
- LeetCode赛题395----Longest Substring with At Least K Repeating Characters
- 【Leetcode】395. Longest Substring with At Least K Repeating Characters
- LeetCode[395] Longest Substring with At Least K Repeating Characters
- leetcode_[python/C++]_395_Longest Substring with At Least K Repeating Characters_(递归非递归)
- Leetcode 395. Longest Substring with At Least K Repeating Characters
- leetcode 395. Longest Substring with At Least K Repeating Characters
- [LeetCode] Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串
- leetcode :Find the contiguous subarray within an array (containing at least one number) which has th
- [Leetcode] 395. Longest Substring with At Least K Repeating Characters 解题报告
- 【Leetcode】395. Longest Substring with At Least K Repeating Characters
- LeetCode No.395 Longest Substring with At Least K Repeating Characters
- leetcode 395. Longest Substring with At Least K Repeating Characters 最长K个数量的字符 + DFS深度优先搜索
- [leetcode]395. Longest Substring with At Least K Repeating Characters
- LeetCode-Longest Substring with At Least K Repeating Characters
- LeetCode 395 Longest Substring with At Least K Repeating Characters
- [LeetCode] 395. Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串
- [LeetCode] 395. Longest Substring with At Least K Repeating Characters