parent
011d4dfa3e
commit
5873ab2c0a
@ -0,0 +1,102 @@
|
|||||||
|
package 第03期.mca_08;
|
||||||
|
|
||||||
|
public class Code01_Trie {
|
||||||
|
|
||||||
|
// 测试链接 : https://leetcode.cn/problems/implement-trie-ii-prefix-tree/
|
||||||
|
// 提交Trie类可以直接通过
|
||||||
|
// 原来代码是对的,但是既然找到了直接测试的链接,那就直接测吧
|
||||||
|
// 这个链接上要求实现的功能和课上讲的完全一样
|
||||||
|
// 该前缀树的路用数组实现
|
||||||
|
class Trie {
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
public int pass;
|
||||||
|
public int end;
|
||||||
|
public Node[] nexts;
|
||||||
|
|
||||||
|
public Node() {
|
||||||
|
pass = 0;
|
||||||
|
end = 0;
|
||||||
|
nexts = new Node[26];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node root;
|
||||||
|
|
||||||
|
public Trie() {
|
||||||
|
root = new Node();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(String word) {
|
||||||
|
if (word == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char[] str = word.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
node.pass++;
|
||||||
|
int path = 0;
|
||||||
|
for (int i = 0; i < str.length; i++) { // 从左往右遍历字符
|
||||||
|
path = str[i] - 'a'; // 由字符,对应成走向哪条路
|
||||||
|
if (node.nexts[path] == null) {
|
||||||
|
node.nexts[path] = new Node();
|
||||||
|
}
|
||||||
|
node = node.nexts[path];
|
||||||
|
node.pass++;
|
||||||
|
}
|
||||||
|
node.end++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void erase(String word) {
|
||||||
|
if (countWordsEqualTo(word) != 0) {
|
||||||
|
char[] chs = word.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
node.pass--;
|
||||||
|
int path = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
path = chs[i] - 'a';
|
||||||
|
if (--node.nexts[path].pass == 0) {
|
||||||
|
node.nexts[path] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node = node.nexts[path];
|
||||||
|
}
|
||||||
|
node.end--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countWordsEqualTo(String word) {
|
||||||
|
if (word == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char[] chs = word.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
index = chs[i] - 'a';
|
||||||
|
if (node.nexts[index] == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
node = node.nexts[index];
|
||||||
|
}
|
||||||
|
return node.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countWordsStartingWith(String pre) {
|
||||||
|
if (pre == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char[] chs = pre.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
index = chs[i] - 'a';
|
||||||
|
if (node.nexts[index] == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
node = node.nexts[index];
|
||||||
|
}
|
||||||
|
return node.pass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package 第03期.mca_08;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Code02_Trie {
|
||||||
|
|
||||||
|
// 测试链接 : https://leetcode.cn/problems/implement-trie-ii-prefix-tree/
|
||||||
|
// 提交Trie类可以直接通过
|
||||||
|
// 原来代码是对的,但是既然找到了直接测试的链接,那就直接测吧
|
||||||
|
// 这个链接上要求实现的功能和课上讲的完全一样
|
||||||
|
// 该前缀树的路用哈希表实现
|
||||||
|
class Trie {
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
public int pass;
|
||||||
|
public int end;
|
||||||
|
public HashMap<Integer, Node> nexts;
|
||||||
|
|
||||||
|
public Node() {
|
||||||
|
pass = 0;
|
||||||
|
end = 0;
|
||||||
|
nexts = new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node root;
|
||||||
|
|
||||||
|
public Trie() {
|
||||||
|
root = new Node();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(String word) {
|
||||||
|
if (word == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char[] chs = word.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
node.pass++;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
index = (int) chs[i];
|
||||||
|
if (!node.nexts.containsKey(index)) {
|
||||||
|
node.nexts.put(index, new Node());
|
||||||
|
}
|
||||||
|
node = node.nexts.get(index);
|
||||||
|
node.pass++;
|
||||||
|
}
|
||||||
|
node.end++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void erase(String word) {
|
||||||
|
if (countWordsEqualTo(word) != 0) {
|
||||||
|
char[] chs = word.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
node.pass--;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
index = (int) chs[i];
|
||||||
|
if (--node.nexts.get(index).pass == 0) {
|
||||||
|
node.nexts.remove(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node = node.nexts.get(index);
|
||||||
|
}
|
||||||
|
node.end--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countWordsEqualTo(String word) {
|
||||||
|
if (word == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char[] chs = word.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
index = (int) chs[i];
|
||||||
|
if (!node.nexts.containsKey(index)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
node = node.nexts.get(index);
|
||||||
|
}
|
||||||
|
return node.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countWordsStartingWith(String pre) {
|
||||||
|
if (pre == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char[] chs = pre.toCharArray();
|
||||||
|
Node node = root;
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < chs.length; i++) {
|
||||||
|
index = (int) chs[i];
|
||||||
|
if (!node.nexts.containsKey(index)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
node = node.nexts.get(index);
|
||||||
|
}
|
||||||
|
return node.pass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package 第03期.mca_08;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
// 设计一个包含一些单词的特殊词典,并能够通过前缀和后缀来检索单词。
|
||||||
|
// 实现 WordFilter 类:
|
||||||
|
// WordFilter(string[] words) 使用词典中的单词 words 初始化对象
|
||||||
|
// f(string pref, string suff)
|
||||||
|
// 返回词典中具有前缀 prefix 和后缀 suff 的单词的下标
|
||||||
|
// 如果存在不止一个满足要求的下标,返回其中 最大的下标
|
||||||
|
// 如果不存在这样的单词,返回 -1 。
|
||||||
|
// 测试链接 : https://leetcode.cn/problems/prefix-and-suffix-search/
|
||||||
|
public class Code03_PrefixAndSuffixSearch {
|
||||||
|
|
||||||
|
// 提交以下这个类
|
||||||
|
class WordFilter {
|
||||||
|
|
||||||
|
class TrieNode {
|
||||||
|
TrieNode[] nexts;
|
||||||
|
ArrayList<Integer> indies;
|
||||||
|
|
||||||
|
public TrieNode() {
|
||||||
|
nexts = new TrieNode[26];
|
||||||
|
indies = new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TrieNode preHead;
|
||||||
|
|
||||||
|
TrieNode sufHead;
|
||||||
|
|
||||||
|
public WordFilter(String[] words) {
|
||||||
|
preHead = new TrieNode();
|
||||||
|
sufHead = new TrieNode();
|
||||||
|
for (int i = 0; i < words.length; i++) {
|
||||||
|
String word = words[i];
|
||||||
|
TrieNode cur = preHead;
|
||||||
|
for (int j = 0; j < word.length(); j++) {
|
||||||
|
int path = word.charAt(j) - 'a';
|
||||||
|
if (cur.nexts[path] == null) {
|
||||||
|
cur.nexts[path] = new TrieNode();
|
||||||
|
}
|
||||||
|
cur = cur.nexts[path];
|
||||||
|
cur.indies.add(i);
|
||||||
|
}
|
||||||
|
cur = sufHead;
|
||||||
|
for (int j = word.length() - 1; j >= 0; j--) {
|
||||||
|
int path = word.charAt(j) - 'a';
|
||||||
|
if (cur.nexts[path] == null) {
|
||||||
|
cur.nexts[path] = new TrieNode();
|
||||||
|
}
|
||||||
|
cur = cur.nexts[path];
|
||||||
|
cur.indies.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int f(String pref, String suff) {
|
||||||
|
ArrayList<Integer> preList = null;
|
||||||
|
TrieNode cur = preHead;
|
||||||
|
for (int i = 0; i < pref.length() && cur != null; i++) {
|
||||||
|
cur = cur.nexts[pref.charAt(i) - 'a'];
|
||||||
|
}
|
||||||
|
if (cur != null) {
|
||||||
|
preList = cur.indies;
|
||||||
|
}
|
||||||
|
if (preList == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ArrayList<Integer> sufList = null;
|
||||||
|
cur = sufHead;
|
||||||
|
for (int i = suff.length() - 1; i >= 0 && cur != null; i--) {
|
||||||
|
cur = cur.nexts[suff.charAt(i) - 'a'];
|
||||||
|
}
|
||||||
|
if (cur != null) {
|
||||||
|
sufList = cur.indies;
|
||||||
|
}
|
||||||
|
if (sufList == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ArrayList<Integer> small = preList.size() <= sufList.size() ? preList : sufList;
|
||||||
|
ArrayList<Integer> big = small == preList ? sufList : preList;
|
||||||
|
for (int i = small.size() - 1; i >= 0; i--) {
|
||||||
|
if (bs(big, small.get(i))) {
|
||||||
|
return small.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean bs(ArrayList<Integer> sorted, int num) {
|
||||||
|
int l = 0;
|
||||||
|
int r = sorted.size() - 1;
|
||||||
|
int m = 0;
|
||||||
|
int midValue = 0;
|
||||||
|
while (l <= r) {
|
||||||
|
m = (l + r) / 2;
|
||||||
|
midValue = sorted.get(m);
|
||||||
|
if (midValue == num) {
|
||||||
|
return true;
|
||||||
|
} else if (midValue < num) {
|
||||||
|
l = m + 1;
|
||||||
|
} else {
|
||||||
|
r = m - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package 第03期.mca_07;
|
package 第03期.mca_08;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
@ -1,4 +1,4 @@
|
|||||||
package 第03期.mca_07;
|
package 第03期.mca_08;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
Loading…
Reference in new issue