Java - rolling window w/ explanation
\nclass Solution {\n    public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {\n        int max = 0;\n        HashMap<Character, Integer> uniq
```\nclass Solution {\n    public int maxFreq(String s, int maxLetters, int minSize, int maxSize) {\n        int max = 0;\n        HashMap<Character, Integer> uniques = new HashMap<>(); // used to count character occurences\n        HashMap<String, Integer> counts = new HashMap<>(); // used to count valid substrings\n        \n        for (int i = 0, j = 0; i < s.length(); i++) { // i = right pointer, j = left pointer\n            uniques.put(s.charAt(i), uniques.getOrDefault(s.charAt(i), 0) + 1);\n\t\t\t\n\t\t\t// If the window is invalid (i.e. window size is too big or there are too many unique letters),\n\t\t\t// shrink the window until it\'s valid again.\n            while (i - j + 1 > maxSize || uniques.size() > maxLetters) { // "+ 1" is needed because both pointers are 0 indexed\n                removeChar(uniques, s.charAt(j++));\n            }\n\t\t\t\n\t\t\t// At this point we can guarantee that the current window is valid due to the above while loop.\n\t\t\t// Now we need to check all substrings from the current size to the smallest size.\n            while (i - j + 1 >= minSize) {\n                String substr = s.substring(j, i + 1);\n                counts.put(substr, counts.getOrDefault(substr, 0) + 1);\n                max = Math.max(max, counts.get(substr));\n                removeChar(uniques, s.charAt(j++));\n            }\n        }\n\n        return max;\n    }\n    \n    private void removeChar(HashMap<Character, Integer> uniques, char c) {\n        uniques.put(c, uniques.getOrDefault(c, 0) - 1);\n        if (uniques.get(c) == 0) uniques.remove(c);\n    }\n}\n```
[]