Well explained Java solution !!!
IntuitionThe problem requires counting substrings that contain at least one occurrence of 'a', 'b', and 'c'.
A brute-force approach would check all substrings,
# Intuition
The problem requires counting substrings that contain at least one occurrence of 'a', 'b', and 'c'.  
A brute-force approach would check all substrings, but that would be inefficient.  
Instead, we can use a **sliding window** (two-pointer) approach to efficiently count valid substrings.

## Why do we shrink the window?
- Once we find a valid substring that contains 'a', 'b', and 'c', we **know** that:
  - Any substring that starts at `i` and extends beyond `j` is also valid.
  - The total count for this window is `(len - j)`, since all substrings `[i, j]`, `[i, j+1]`, ... `[i, len-1]` are valid.
- To avoid overcounting, we **shrink the window** by increasing `i`, checking if we can still maintain a valid substring.
- This ensures we efficiently count all required substrings in **linear time**.

# Approach
- Use two pointers (`i` and `j`) to define a sliding window.
- Maintain a **HashMap** to track the frequency of characters in the window.
- Expand the window by increasing `j` and updating the frequency map.
- When the window contains all three characters ('a', 'b', and 'c'), count all substrings starting from `i` and shrink the window from the left by increasing `i` while maintaining validity.
- This ensures we efficiently count all required substrings in **linear time**.

# Complexity
- **Time complexity:**  
  - Each character is processed at most twice (once when expanding and once when contracting).  
  - Thus, the time complexity is **$$O(n)$$**, where $$n$$ is the length of the string.

- **Space complexity:**  
  - The HashMap stores at most **three** characters ('a', 'b', 'c'), so its size is **constant**.
  - Thus, the space complexity is **$$O(1)$$**.

# Code
```java
class Solution {
    public int numberOfSubstrings(String s) {
        int i = 0, j = 0, ans = 0, len = s.length(), ct;
        HashMap<Character, Integer> mp = new HashMap<>();
        
        while (j < len) {
            mp.put(s.charAt(j), mp.getOrDefault(s.charAt(j), 0) + 1);
            
            while (mp.size() == 3) {
                ans += (len - j);
                ct = mp.get(s.charAt(i));
                --ct;
                
                if (ct == 0) {
                    mp.remove(s.charAt(i));
                } else {
                    mp.put(s.charAt(i), ct);
                }
                
                ++i;
            }
            ++j;
        }
        return ans;
    }
}

['Java']