Advertisement
Iam_Sandeep

862. Shortest Subarray with Sum at Least K

Jun 17th, 2022 (edited)
1,467
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.59 KB | None | 0 0
  1. class Solution:
  2.     def shortestSubarray(self, A: List[int], k: int) -> int:
  3.         q=deque()
  4.         n=len(A)
  5.         B=[0]*(n+1)
  6.  '''
  7. B is used for cumulative sum. Remember cumulative size array is of (n+1) length.
  8. '''
  9.         for i in range(n):
  10.             B[i+1]=B[i]+A[i]
  11.            
  12.         ans=float('inf')
  13.    
  14.         for i in range(n+1):
  15.             while q and B[i]-B[q[0]]>=k:
  16.                 ans=min(ans,i-q[0])#Because B[i]-B[q[0]] stores sum between q[0] and i-1 (including ends). Hence diff =i-1-q[0]+1........(r-l+1)
  17.                 q.popleft()
  18.             while q and B[i]<=B[q[-1]]:
  19.                 q.pop()
  20.             q.append(i)
  21.         return ans if ans<=n else -1
  22.    '''
  23. Explanation
  24. Calculate prefix sum B of list A.
  25. B[j] - B[i] represents the sum of subarray A[i] ~ A[j-1]
  26. Deque d will keep indexes of increasing B[i].
  27. For every B[i], we will compare B[i] - B[d[0]] with K.
  28.  
  29.  
  30. Complexity:
  31. Every index will be pushed exactly once.
  32. Every index will be popped at most once.
  33.  
  34. Time O(N)
  35. Space O(N)
  36.  
  37.  
  38. How to think of such solutions?
  39. Basic idea, for array starting at every A[i], find the shortest one with sum at leat K.
  40. In my solution, for B[i], find the smallest j that B[j] - B[i] >= K.
  41. Keep this in mind for understanding two while loops.
  42.  
  43.  
  44. What is the purpose of first while loop?
  45. For the current prefix sum B[i], it covers all subarray ending at A[i-1].
  46. We want know if there is a subarray, which starts from an index, ends at A[i-1] and has at least sum K.
  47. So we start to compare B[i] with the smallest prefix sum in our deque, which is B[D[0]], hoping that [i] - B[d[0]] >= K.
  48. So if B[i] - B[d[0]] >= K, we can update our result res = min(res, i - d.popleft()).
  49. The while loop helps compare one by one, until this condition isn't valid anymore.
  50.  
  51.  
  52. Why we pop left in the first while loop?
  53. This the most tricky part that improve my solution to get only O(N).
  54. D[0] exists in our deque, it means that before B[i], we didn't find a subarray whose sum at least K.
  55. B[i] is the first prefix sum that valid this condition.
  56. In other words, A[D[0]] ~ A[i-1] is the shortest subarray starting at A[D[0]] with sum at least K.
  57. We have already find it for A[D[0]] and it can't be shorter, so we can drop it from our deque.
  58.  
  59.  
  60. What is the purpose of second while loop?
  61. To keep B[D[i]] increasing in the deque.
  62.  
  63.  
  64. Why keep the deque increase?
  65. If B[i] <= B[d.back()] and moreover we already know that i > d.back(), it means that compared with d.back(),
  66. B[i] can help us make the subarray length shorter and sum bigger. So no need to keep d.back() in our deque.
  67.   '''
  68.    
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement