- 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
- 46 lines of Java from the credited upstream file 3104.java.
- The implementation visibly relies on sequence storage.
- 4 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 int maxSubstringLength(String s) {3 int ans = -1;4 int count[] = new int[26];5 6 for (final char c : s.toCharArray())7 ++count[c - 'a'];8 9 for (int n = 1; n <= 26; ++n)10 ans = Math.max(ans, maxSubstringLengthWithNUniqueLetters(s, n, count));11 12 return ans;13 }14 15 16 private int maxSubstringLengthWithNUniqueLetters(final String s, int n, int[] allCount) {17 int res = -1;18 19 int uniqueLetters = 0;20 21 int lettersHavingAllFreq = 0;22 int[] count = new int[26];23 24 for (int l = 0, r = 0; r < s.length(); ++r) {25 if (++count[s.charAt(r) - 'a'] == 1)26 ++uniqueLetters;27 if (count[s.charAt(r) - 'a'] == allCount[s.charAt(r) - 'a'])28 ++lettersHavingAllFreq;29 while (uniqueLetters > n) {30 if (count[s.charAt(l) - 'a'] == allCount[s.charAt(l) - 'a'])31 --lettersHavingAllFreq;32 if (--count[s.charAt(l) - 'a'] == 0)33 --uniqueLetters;34 ++l;35 }36 37 38 39 if (lettersHavingAllFreq == n && r - l + 1 < s.length())40 res = Math.max(res, r - l + 1);41 }42 43 return res;44 }45}46