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")
Y2xhc3MgU29sdXRpb24ob2JqZWN0KToKICAgIGRlZiBsb25nZXN0U3Vic3RyaW5nKHNlbGYsIHMsIGspOgogICAgICAgICIiIgogICAgICAgIDp0eXBlIHM6IHN0cgogICAgICAgIDp0eXBlIGs6IGludAogICAgICAgIDpydHlwZTogaW50IChyZXR1cm5zIHRoZSBsZW5ndGggb2YgdGhlIGxvbmdlc3Qgc3Vic3RyaW5nKQogICAgICAgICIiIgogICAgICAgIGkgPSAwCiAgICAgICAgbWF4X2xlbiA9IDAKICAgICAgICBjb3VudHMgPSB7fSAgIyBUcmFja3MgY2hhcmFjdGVyIGZyZXF1ZW5jaWVzIGluIHRoZSBjdXJyZW50IHdpbmRvdwogICAgICAgIAogICAgICAgIGZvciBqIGluIHJhbmdlKGxlbihzKSk6CiAgICAgICAgICAgICMgRXhwYW5kIHdpbmRvdzogYWRkIGN1cnJlbnQgY2hhcmFjdGVyIHRvIGZyZXF1ZW5jeSBtYXAKICAgICAgICAgICAgY291bnRzW3Nbal1dID0gY291bnRzLmdldChzW2pdLCAwKSArIDEKICAgICAgICAgICAgCiAgICAgICAgICAgICMgU2hyaW5rIHdpbmRvdzogd2hpbGUgbWF4IGNoYXIgQVNDSUkgLSBtaW4gY2hhciBBU0NJSSA+IGssIHJlbW92ZSBmcm9tIGxlZnQKICAgICAgICAgICAgIyBvcmQoKSBjb252ZXJ0cyBjaGFyYWN0ZXJzIGxpa2UgJ2EnIHRvIDk3LCAneicgdG8gMTIyLCBldGMuCiAgICAgICAgICAgIHdoaWxlIG1heChvcmQoY2gpIGZvciBjaCBpbiBjb3VudHMpIC0gbWluKG9yZChjaCkgZm9yIGNoIGluIGNvdW50cykgPiBrOgogICAgICAgICAgICAgICAgY291bnRzW3NbaV1dIC09IDEKICAgICAgICAgICAgICAgIGlmIGNvdW50c1tzW2ldXSA9PSAwOgogICAgICAgICAgICAgICAgICAgIGRlbCBjb3VudHNbc1tpXV0gICMgUmVtb3ZlIGtleSBzbyBpdCBkb2Vzbid0IGFmZmVjdCBtaW4vbWF4CiAgICAgICAgICAgICAgICBpICs9IDEKICAgICAgICAgICAgCiAgICAgICAgICAgICMgQ2FsY3VsYXRlIGN1cnJlbnQgd2luZG93IHNpemUgYW5kIHVwZGF0ZSBtYXhpbXVtIGxlbmd0aAogICAgICAgICAgICBjdXJyZW50X2xlbiA9IGogLSBpICsgMQogICAgICAgICAgICBpZiBjdXJyZW50X2xlbiA+IG1heF9sZW46CiAgICAgICAgICAgICAgICBtYXhfbGVuID0gY3VycmVudF9sZW4KICAgICAgICAgICAgICAgIAogICAgICAgIHJldHVybiBtYXhfbGVuCgojIEV4YW1wbGU6CiMgc29sID0gU29sdXRpb24oKQojIHByaW50KHNvbC5sb25nZXN0U3Vic3RyaW5nKCJhemJjYSIsIDIpKSAjIFJldHVybnMgMyAoc3Vic3RyaW5nICJiY2EiIG9yICJhYmMiKQo=