算法每一题,成长每一天~
C0E3 数大雁
思路
Java
import java.util.*;
import java.util.stream.Collectors;
public class C0E3 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String line = in.nextLine();
if (line.length() < 5) {
System.out.println("-1");
return;
}
/*if (line.equals("quack")) {
System.out.println("1");
return;
}
boolean flag = line.contains("quack");
line = line.replaceAll("quack", "");*/
char[] arr = line.toCharArray();
int[] visited = new int[arr.length];
int r = 0; // 'k'的个数
Map<Integer, List<Integer>> kMap = new TreeMap<>();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 'k') {
kMap.computeIfAbsent(r++, k -> new ArrayList<>())
.add(i); // 'k'的索引放到第0个了,所以后面'q'将放到第1个...
}
}
// 遍历字符数组,并逐次放到k个桶中
int qIdx = 0, uIdx = 0, aIdx = 0, cIdx = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 'q' && qIdx < r) {
kMap.get(qIdx++) // q的索引
.add(i);
} else if (arr[i] == 'u' && uIdx < r) {
kMap.get(uIdx++) // u的索引
.add(i);
} else if (arr[i] == 'a' && aIdx < r) {
kMap.get(aIdx++) // a的索引
.add(i);
} else if (arr[i] == 'c' && cIdx < r) {
kMap.get(cIdx++) // c的索引
.add(i);
}
}
List<List<Integer>> resultList = kMap.values()
.stream()
.filter(l -> l.size() >= 5) // 过滤出完整的 quack
.sorted(Comparator.comparingInt(l -> l.get(0))) // 按 k 排序
.collect(Collectors.toList());
int minNum = resultList.size();
int[] k = new int[minNum];
int[] q = new int[minNum];
for (int i = 0; i < minNum; i++) {
k[i] = resultList.get(i).get(0);
q[i] = resultList.get(i).get(1);
}
int s = 0;
for (int kIndex : k) {
// 如有有q的索引位置在 k之后,则该k不算个数,从minNum中-1
for (int j = s; j < q.length; j++) {
int qIndex = q[j];
if (qIndex > kIndex) {
minNum--;
s = j;
break;
}
}
}
/*// 如果前面剔除了 "quack",那至少有一个大雁
if (minNum < 1 && flag) {
minNum = 1;
}*/
System.out.println(minNum);
}
}
总结
1、思路中的第2,3点多余,因为后面的逻辑已经包含这种情况。
2、第5点多余,因为对字符串只从头到尾遍历了一次,并逐次放到k个桶中,所以visited状态不需要。
3、第7点,写的时候发现使用 Map与List的组合更好,因为数组不便于判断 每个桶中字符的个数是否有5个。
4、最后一点非常重要,是求大雁数最少的关键!
简化后,思路如下:
xx:做完再回头看,感觉逻辑也不难,除了最后一点需要多考虑下~
算法要多练多练多练!!