题目要求统计abb字串格式。
输入:abcbcc
输出:8
输入:abbb
输出:3
下面是我做的对比,对于普通for循环和手写算法比较,输入5k个字符,手写算法用时为27ms,普通for循环用时43.773s,经测试,结果是一致的。
原理引入:ABABCB
第一次输入 A 当前map(字符计数器)中A为0
更新map表A个数=1,加入listMap(字符前个数)表索引A,并加入队列0,因为A前面没有字符。
第二次输入 B 当前map(字符计数器)中B为0
更新map表B个数=1,加入listMap(字符前个数)表索引B,并加入队列1,因为B前面有1个字符。
第三次输入 A 当前map(字符计数器)中A为1
更新map表A个数=2,遍历在listMap(字符前个数)表索引A队列,因为第一个A前面没有字符,所以也就不存在ABB格式。加入当前字符A前面除A以外的字符数【1】到listMap表A队列中.
第四次输入 B 当前map(字符计数器)中B为1
更新map表B个数=2,遍历在listMap(字符前个数)表索引B队列,因为第一个B前面有1个字符,所以也就存在1个ABB格式的子串,更新c(计数器)为1。再加入当前字符B前面除B以外的字符数【2】到listMap表B队列中.
第五次输入 C 当前map(字符计数器)中C为0
更新map表C个数=1,遍历在listMap(字符前个数)表索引C队列,因为C队列才开始,所以队列为0.再加入当前字符C前面除C以外的字符数【4】到listMap表C队列中.
第六次输入 B 当前map(字符计数器)中B为2
更新map表B个数=3,遍历在listMap(字符前个数)表索引B队列,因为第一个B前面有1个字符,第二个B字符前面有2个字符,所以也就存在【2+1】个ABB格式的子串,更新c(计数器)为4。再加入当前字符B前面除B以外的字符数【3】到listMap表B队列中.
所以最终ABB格式的子串个数为4.
A(第一个位置)B(第二个位置)B(第四个位置)
A(第一个位置)B(第二个位置)B(第六个位置)
A(第一个位置)B(第四个位置)B(第六个位置)
A(第三个位置)B(第四个位置)B(第六个位置)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
String line = sc.next();
long st=System.nanoTime();
a3(line);
long st1=System.nanoTime();
a2(line);
long st2=System.nanoTime();
System.out.println("time compare:"+((st1-st)/1000000)+"ms|"+((st2-st1)/1000000)+"ms");
}
public static void a3(String a3){
Map <Character,List<Integer>> listMap=new HashMap<>();//记录相同字符不同位置的前面非本字符的个数。
Map<Character,Integer> map=new HashMap<>();//字符计数器
int c=0;//ABB 统计
for (int i = 0; i < a3.length(); i++) {
char s=a3.charAt(i); //获取字符
int count=map.getOrDefault(s,0)+1; //获取表中存储得字符个数。
map.put(s,count); //更新字符个数。
List<Integer> t=listMap.get(s); //获取该字符的队列
if(t==null){t=new LinkedList<>();listMap.put(s,t);}//初始化队列
if(t.size()>0){ //如果该字符表里已经有1个了,就存在ABB。
for (int k : t) { //遍历队列
c+=k; //计数器操作
}
}
t.add((i+1)-count); //加入当前位置前面的字符个数并减去当前字符的个数。
}
System.out.println(c); //打印ABB的个数。
}
public static void a2(String line2){
int t=0;
for (int i = 0; i < line2.length()-2; i++) {
for (int j = i+1; j < line2.length()-1; j++) {
for (int k = j+1; k < line2.length(); k++) {
if(line2.charAt(i)!=line2.charAt(j) &&
line2.charAt(j)==line2.charAt(k)){
t++;
}
}
}
}
System.out.println(t);
}
}