โจทย์: Longest Repeating Character Replacement
ให้สตริง s ประกอบด้วยตัวพิมพ์ใหญ่ (A-Z) เท่านั้น สามารถทำการ เปลี่ยนตัวอักษรได้สูงสุด k ครั้ง** (แต่ละครั้ง เปลี่ยนตัวอักษรตัวใดตัวหนึ่งเป็นตัวอักษรพิมพ์ใหญ่อื่น) ต้องหา ความยาวสูงสุด** ของ substring ที่มี ตัวอักษรเดียวกันทั้งหมด** หลังจากเปลี่ยนได้สูงสุด k ครั้ง
ตัวอย่าง: s = "ABAB", k = 2
เปลี่ยน 2 ตัว 'B' → 'A' ได้ "AAAA" ความยาว 4 → ผลลัพธ์: 4
อัลกอริทึม: Sliding Window + Character Count
รักษาหน้าต่าง [left, right] ที่เป็น "valid" = สามารถเปลี่ยนตัวอักษรในหน้าต่างให้เหมือนกันทั้งหมดได้ภายใน k ครั้ง
เงื่อนไข valid: window_size - max_frequency_in_window <= k
(จำนวนตัวที่ต้องเปลี่ยน = ขนาดหน้าต่าง - จำนวนตัวอักษรที่พบบ่อยที่สุดในหน้าต่าง)
maxCount = 0, ans = 0, left = 0count[26] = {0}นับความถี่ในหน้าต่างปัจจุบัน- วน
right = 0..n-1(ขยายขวา):count[s[right]-'A']++maxCount = max(maxCount, count[s[right]-'A'])- ในขณะที่
(right - left + 1) - maxCount > k(invalid):count[s[left]-'A']--(หดซ้าย)left++
ans = max(ans, right - left + 1)
- ส่งคืน
ans
จุดสำคัญ: maxCount ไม่ต้องลดลงเมื่อหดหน้าต่างซ้าย เพราะเราหา ค่าสูงสุดที่เคยเจอ** ไม่ใช่ค่าปัจจุบันในหน้าต่าง การที่ maxCount เก่ากว่าจริง ทำให้เงื่อนไข strict กว่า แต่ก็ยังถูกต้อง (อาจพลาดคำตอบที่ดีกว่าเล็กน้อยแต่ในทางปฏิบัติถูกต้องเสมอ)
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int characterReplacement(string s, int k) {
vector<int> count(26, 0);
int maxCount = 0;
int ans = 0;
int left = 0;
for (int right = 0; right < s.size(); right++) {
count[s[right] - 'A']++;
maxCount = max(maxCount, count[s[right] - 'A']);
// หน้าต่างไม่ valid: ต้องเปลี่ยนมากกว่า k ตัว
while (right - left + 1 - maxCount > k) {
count[s[left] - 'A']--;
left++;
}
ans = max(ans, right - left + 1);
}
return ans;
}
};
int main() {
Solution ob;
cout << ob.characterReplacement("ABAB", 2) << endl;
return 0;
}
Input
"ABAB" 2
Output
4
ความซับซ้อน (Complexity)
- เวลา: O(n) - แต่ละตัวอักษรเข้าออกหน้าต่างได้สูงสุด 1 ครั้ง
- พื้นที่: O(1) - array 26 ตัว