Cho chuỗi s chữ thường độ dài chẵn. Cần tìm số ký tự ít nhất phải thay đổi để nửa đầu và nửa sau thỏa mãn một trong 3 điều kiện cho mọi cặp (i, j) với i < n/2, j >= n/2:
s[i] > s[j](nửa đầu > nửa sau)s[i] < s[j](nửa đầu < nửa sau)s[i] == s[j](nửa đầu = nửa sau)
Ví dụ
s = "pppxxp" (n=6, nửa đầu="ppp", nửa sau="xxp") → Output: 1
Thay 'p' cuối cùng thành 'x' → "pppxxx" thỏa s[i] < s[j] (p < x).
Thuật toán
- Đếm tần suất ký tự nửa trái (
left) và nửa phải (right). - Duyệt mọi ký tự
pivottừ 'a' đến 'z': - Trường hợp 1 (bằng nhau): đổi tất cả thành
pivot→ cost = n - left[pivot] - right[pivot]. - Trường hợp 2 (trái < phải): trái ≤ pivot, phải > pivot → cost = n - good.
- Trường hợp 3 (trái > phải): trái > pivot, phải ≤ pivot → cost = n - good.
- Lấy min của tất cả.
Code Python
from collections import Counter
from string import ascii_lowercase
def solve(s):
n = len(s)
left = Counter(s[:n//2])
right = Counter(s[n//2:])
ans = n
for pivot in ascii_lowercase:
# Trường hợp 1: tất cả bằng pivot
ans = min(ans, n - left[pivot] - right[pivot])
# Trường hợp 2: trái <= pivot < phải
good = sum(left[c] for c in left if c <= pivot)
good += sum(right[c] for c in right if c > pivot)
ans = min(ans, n - good)
# Trường hợp 3: trái > pivot >= phải
good = sum(left[c] for c in left if c > pivot)
good += sum(right[c] for c in right if c <= pivot)
ans = min(ans, n - good)
return ans
# Test
print(solve("pppxxp")) # 1
print(solve("aaaaaa")) # 0 (đã bằng nhau)
print(solve("abcdef")) # 2
Giải thích ví dụ "pppxxp"
left = {p:3}
right = {x:2, p:1}
pivot='p':
equal: 6 - 3 - 1 = 2
left<=p cost=1 <-- MIN
left>p>=right: 0 + right[p]=1 = 1 -> cost=5
Độ phức tạp
- Thời gian:
O(26 × n)=O(n)(26 là hằng số alphabet). - Không gian:
O(1)(Counter tối đa 26 keys).