Description
You are given a string s
and an integer k
. Your task is to find the maximum difference between the frequency of two characters, freq[a] - freq[b]
, in a substring subs
of s
, such that:
subs
has a size of at leastk
.- Character
a
has an odd frequency insubs
. - Character
b
has a non-zero even frequency insubs
.
Return the maximum difference.
Note that subs
can contain more than 2 distinct characters.
Β
Example 1:
Input: s = "12233", k = 4
Output: -1
Explanation:
For the substring "12233"
, the frequency of '1'
is 1 and the frequency of '3'
is 2. The difference is 1 - 2 = -1
.
Example 2:
Input: s = "1122211", k = 3
Output: 1
Explanation:
For the substring "11222"
, the frequency of '2'
is 3 and the frequency of '1'
is 2. The difference is 3 - 2 = 1
.
Example 3:
Input: s = "110", k = 3
Output: -1
Β
Constraints:
3 <= s.length <= 3 * 104
s
consists only of digits'0'
to'4'
.- The input is generated that at least one substring has a character with an even frequency and a character with an odd frequency.
1 <= k <= s.length
Solution
Python3
import numpy as np
class Solution:
def maxDifference(self, s: str, k: int) -> int:
n = len(s)
arr = np.frombuffer(s.encode('ascii'), dtype=np.uint8) - ord('0')
pre = np.empty((5, n), dtype=np.int64)
for x in range(5):
is_x = (arr == x).astype(np.int64)
pre[x] = np.cumsum(is_x)
closest_right = np.full((5, n), n, dtype=np.int64)
for x in range(5):
indices = np.flatnonzero(arr == x)
if indices.size:
pos = np.searchsorted(indices, np.arange(n))
valid = pos < indices.size
closest_right[x, valid] = indices[pos[valid]]
best = -10**9
for odd in range(5):
for even in range(5):
if odd == even:
continue
odd_pre = pre[odd]
even_pre = pre[even]
odd_parity = (odd_pre % 2).astype(np.int64)
even_parity = (even_pre % 2).astype(np.int64)
suf = np.full((2, 2, n), -10**9, dtype=np.int64)
valid_mask = (odd_pre > 0) & (even_pre > 0)
diff = odd_pre - even_pre
idx = np.where(valid_mask)[0]
suf[odd_parity[idx], even_parity[idx], idx] = diff[idx]
for p in (0, 1):
for q in (0, 1):
suf[p, q] = np.maximum.accumulate(suf[p, q][::-1])[::-1]
m = n - k + 1
start_idx = np.arange(m, dtype=np.int64)
odd_below = np.where(start_idx == 0, 0, odd_pre[start_idx - 1])
even_below = np.where(start_idx == 0, 0, even_pre[start_idx - 1])
good_odd_parity = (odd_below + 1) % 2
good_even_parity = even_below % 2
q1 = start_idx + k - 1
q2 = closest_right[odd, start_idx]
q3 = closest_right[even, start_idx]
query = np.maximum.reduce([q1, q2, q3])
valid_q = query < n
candidate = -10**9 * np.ones(m, dtype=np.int64)
for p in (0, 1):
for q in (0, 1):
mask = (good_odd_parity == p) & (good_even_parity == q) & valid_q
if np.any(mask):
candidate[mask] = np.maximum(candidate[mask],
suf[p, q][query[mask]] - odd_below[mask] + even_below[mask])
best = max(best, candidate.max())
return int(best)