【编码题】字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?
输入描述:
第一行为一个字符串S与一个非负整数m。(1 <= |S| <= 1000, 1 <= m <= 1000000)
输出描述:
一个非负整数,表示操作之后,连续最长的相同字母数量。
输入例子1:
abcbaa 2
输出例子1:
2
package test;
import java.util.*;
public class CharMax {
public static void main (String[] args) {
HashMap<Character, ArrayList<Integer>> hs = new HashMap<>();
int max = 0;//最大连续数
Scanner sc = new Scanner(System.in);
String[] arr = sc.nextLine().split("\\s+");
String str = arr[0];
int steps = Integer.parseInt(arr[1]);//总步长
//准备工作
for(int i=0; i < str.length(); i++){
char c = str.charAt(i);
ArrayList<Integer> ls = new ArrayList<>();
if (hs.get(c) != null){
ls = hs.get(c);
}
ls.add(i);
hs.put(c, ls);
}
//开始计算
for (char key : hs.keySet()){
ArrayList<Integer> ls = hs.get(key);
int len = ls.size();
if (len <= max)
continue;
if (len == 1){
max = 1;
continue;
}
for (int i=0; i < ls.size()-1; i++){
int total = 1;//统计连续数
int rest = steps;//可走步长数
int l = i;//左边界
int r = i;//右边界
while( l > 0 || r < ls.size()-1){
//左右边界距离下一个有效值计算
int l_len = Integer.MAX_VALUE;//左边距
int r_len = Integer.MAX_VALUE;//右边距
if (l > 0){
l_len = (ls.get(i) - (i-l)) - ls.get(l-1) - 1;
}
if (r < ls.size()-1){
r_len = ls.get(r+1) - (ls.get(i) + (r-i)) - 1;
}
if (l_len < r_len){//左边距 < 右边距
rest -= l_len;
if (rest < 0)
break;
l--;//边界变更
total++;
}else{
rest -= r_len;
if (rest < 0)
break;
r++;
total++;
}
}
if (total > max)
max = total;
}
}
System.out.println(max);
}
}
//hkdbqojqvxlfulshrhpysezhlyzolb 20
//4
//abcbaa 2
// 2