class Solution(object):
    def longestSubstring(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int (returns the length of the longest substring)
        """
        i = 0
        max_len = 0
        counts = {}  # Tracks character frequencies in the current window
        
        for j in range(len(s)):
            # Expand window: add current character to frequency map
            counts[s[j]] = counts.get(s[j], 0) + 1
            
            # Shrink window: while max char ASCII - min char ASCII > k, remove from left
            # ord() converts characters like 'a' to 97, 'z' to 122, etc.
            while max(ord(ch) for ch in counts) - min(ord(ch) for ch in counts) > k:
                counts[s[i]] -= 1
                if counts[s[i]] == 0:
                    del counts[s[i]]  # Remove key so it doesn't affect min/max
                i += 1
            
            # Calculate current window size and update maximum length
            current_len = j - i + 1
            if current_len > max_len:
                max_len = current_len
                
        return max_len

# Example:
# sol = Solution()
# print(sol.longestSubstring("azbca", 2)) # Returns 3 (substring "bca" or "abc")
