问题描述
小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。
测试样例
样例1:
输入:
input = "ADDF"
输出:1
样例2:
输入:
input = "ASAFASAFADDD"
输出:3
样例3:
输入:
input = "SSDDFFFFAAAS"
输出:1
样例4:
输入:
input = "AAAASSSSDDDDFFFF"
输出:0
样例5:
输入:
input = "AAAADDDDAAAASSSS"
输出:4
解题思路
先用一个 HashMap 来映射字符 A、S、D、F 到索引,然后用一个数组 counts 来记录每个字符的出现次数。接着计算理想频次(字符串长度除以 4),并遍历 counts 数组,计算每个字符的频次与理想频次的差异,累加需要替换的字符总数。最后,如果所有字符的频次已经相等,则返回 0;否则,返回需要替换的字符总数。
算法步骤
-
初始化:
- 使用
HashMap将字符A、S、D、F映射到索引0、1、2、3。 - 初始化一个长度为 4 的数组
counts,用于记录每个字符的出现次数。
- 使用
-
统计频次:
- 遍历输入字符串
input,根据HashMap获取每个字符的索引,并在counts数组中相应位置累加出现次数。
- 遍历输入字符串
-
计算理想频次:
- 计算理想频次
len,即字符串长度除以 4。
- 计算理想频次
-
计算差异:
- 遍历
counts数组,计算每个字符的频次与理想频次的差异,并累加需要替换的字符总数res。
- 遍历
-
返回结果:
- 返回需要替换的字符总数
res。
- 返回需要替换的字符总数
代码实现
import java.util.HashMap;
import java.util.HashSet;
public class Main {
static HashMap<Character, Integer> hm = new HashMap<>();
static {
hm.put('A', 0);
hm.put('D', 1);
hm.put('S', 2);
hm.put('F', 3);
}
static int[] counts;
static HashSet<Integer> hs;
public static int solution(String input) {
counts = new int[4];
hs = new HashSet<>();
// Please write your code here
int res = input.length();
int len = input.length() / 4;
for(int i = 0; i < input.length(); i++){
char c = input.charAt(i);
counts[hm.get(c)]++;
}
for(int i = 0; i < 4 ; i++){
if(counts[i] > len) hs.add(i);
}
if(hs.size() == 0) return 0;
for(int right = 0, left = 0; right < input.length(); right++){
int idx = hm.get(input.charAt(right));
if(hs.contains(idx)){
counts[idx]--;
while(isenough(len)){
res = Math.min(res, right - left + 1);
int idx2 = hm.get(input.charAt(left));
if(hs.contains(idx2)) counts[idx2]++;
left++;
}
}
}
return res;
}
public static boolean isenough(int len){
for(Integer key : hs.toArray(new Integer[0])){
if(counts[key] > len ) return false;
}
return true;
}
}