- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 58 lines of Java from the credited upstream file 3261.java.
- The implementation visibly relies on sequence storage.
- 6 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public long[] countKConstraintSubstrings(String s, int k, int[][] queries) {3 final int n = s.length();4 long[] ans = new long[queries.length];5 int[] count = new int[2];6 7 int[] leftToRight = new int[n];8 9 int[] rightToLeft = new int[n];10 11 long[] prefix = new long[n + 1];12 13 for (int l = 0, r = 0; r < n; ++r) {14 ++count[s.charAt(r) - '0'];15 while (count[0] > k && count[1] > k)16 --count[s.charAt(l++) - '0'];17 rightToLeft[r] = l;18 }19 20 Arrays.fill(count, 0);21 22 for (int l = n - 1, r = n - 1; l >= 0; --l) {23 ++count[s.charAt(l) - '0'];24 while (count[0] > k && count[1] > k)25 --count[s.charAt(r--) - '0'];26 leftToRight[l] = r;27 }28 29 for (int r = 0; r < n; ++r)30 prefix[r + 1] = prefix[r] + r - rightToLeft[r] + 1;31 32 for (int i = 0; i < queries.length; ++i) {33 final int l = queries[i][0];34 final int r = queries[i][1];35 long numValidSubstrings = 0;36 if (r > leftToRight[l]) {37 38 39 40 41 42 43 44 45 46 final int sz = leftToRight[l] - l + 1;47 numValidSubstrings = (sz * (sz + 1)) / 2 + (prefix[r + 1] - prefix[leftToRight[l] + 1]);48 } else {49 final int sz = r - l + 1;50 numValidSubstrings = (sz * (long) (sz + 1)) / 2;51 }52 ans[i] = numValidSubstrings;53 }54 55 return ans;56 }57}58