刷算法的心得
前言
刷了270道算法,记录自己的心得体会,主要包括具体题型总结和抽象题型总结。
一、具体题型总结
具体的题型总结就是线性表的数组、链表、队列的操作和应用,树的四种遍历、回溯、剪枝,图的DFS、BFS等,动态规划,前缀树等。
具体可去牛客网完成相应一类知识点的刷题。
二、抽象题型总结
我把每个知识点封装成一个component,如component-DFS、component-动态规划等。把数据结构应用看成plugin来辅助component完成算法题解。两类可自由组合。总结了五种题型。
1、预处理Pre + component
1)单词演变:预处理成图+BFS-component
//单向BFS+代码优化,减少运行时间。
public int ladderLength2(String beginWord, String endWord, List<String> wordList) {
//1-预处理:将worldList中的单词作为一个节点,将其之间的关系映射为图关系,然后物理结构预处理成数组式的邻接表。
//2-BFS操作:通过广度优先搜索来求源点到终点的最短路径。
for (String s : wordList) addEdge(s);
if (!wordId.containsKey(endWord)) return 0;
addEdge(beginWord);
int begin = wordId.get(beginWord), end = wordId.get(endWord);
int[] dis = new int[nodeNum];//用该数组既能记住起点到所有节点的最短路径,还能避免加入以访问过的节点避免死循环。
dis[begin] = 1;
Queue<Integer> queue = new LinkedList<>();
queue.offer(begin);
while (!queue.isEmpty()) {
int cur = queue.poll();
for (Integer id : edge.get(cur)) {
if (dis[id] == 0) {
dis[id] = dis[cur] + 1;
queue.offer(id);
}
if (id == end) return (dis[id] >>> 1) + 1;
}
}
return 0;
}
Map<String, Integer> wordId = new HashMap<>();
List<List<Integer>> edge = new ArrayList<>();
int nodeNum = 0;
private void addEdge(String s) {
addNode(s);
int len = s.length();
char[] chs = s.toCharArray();
for (int i = 0; i < len; i++) {
char originC = chs[i];
chs[i] = '*';
String newWord = String.valueOf(chs);
addNode(newWord);
int idx1 = wordId.get(s), idx2 = wordId.get(newWord);
edge.get(idx1).add(idx2);
edge.get(idx2).add(idx1);
chs[i] = originC;
}
}
private void addNode(String s) {
if (!wordId.containsKey(s)) {
wordId.put(s, nodeNum++);
edge.add(new ArrayList<>());
}
}
//双向BFS,通过减少没必要的distance计算,从而减少计算时间。2^8^ > 2^4^ + 2^4^(毕竟单向广度优先,越往后走,要以指数级扩展。)
public int ladderLength3(String beginWord, String endWord, List<String> wordList) {
for (String s : wordList) addEdge(s);
if (!wordId.containsKey(endWord)) return 0;
addEdge(beginWord);
int begin = wordId.get(beginWord), end = wordId.get(endWord);
int[] dis1 = new int[nodeNum];//用该数组既能记住起点到所有节点的最短路径,还能避免加入以访问过的节点避免死循环。
int[] dis2 = new int[nodeNum];
dis1[begin] = 1;
dis2[end] = 1;
Queue<Integer> queue1 = new LinkedList<>();
Queue<Integer> queue2 =