1、实现前缀树
//Trie(发音类似 “try”)或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼
//写检查。
//
// 请你实现 Trie 类:
//
//
// Trie() 初始化前缀树对象。
// void insert(String word) 向前缀树中插入字符串 word 。
// boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false
// 。
// boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否
//则,返回 false 。
//
//
//
//
// 示例:
//
//
//输入
//[“Trie”, “insert”, “search”, “search”, “startsWith”, “insert”, “search”]
//[[], [“apple”], [“apple”], [“app”], [“app”], [“app”], [“app”]]
//输出
//[null, null, true, false, true, null, true]
//
//解释
//Trie trie = new Trie();
//trie.insert(“apple”);
//trie.search(“apple”); // 返回 True
//trie.search(“app”); // 返回 False
//trie.startsWith(“app”); // 返回 True
//trie.insert(“app”);
//trie.search(“app”); // 返回 True
//
//
//
//
// 提示:
//
//
// 1 <= word.length, prefix.length <= 2000
// word 和 prefix 仅由小写英文字母组成
// insert、search 和 startsWith 调用次数 总计 不超过 3 * 104 次
//
// Related Topics 设计 字典树 哈希表 字符串
我们还是以树状结构来对前缀树进行构造,首先每个前缀树节点需要有两个元素:26个子节点以及在该节点处是不是一个单词的结束。据此可以轻松写出成员变量和构造方法:
class Trie {
//一个节点的子节点,一共可能有26种情况
private Trie[] children;
//判断是否已经到了前缀树的末端
private boolean isEnd;
/** Initialize your data structure here. */
public Trie() {
children = new Trie[26];
isEnd = false;
}
其次就是嵌入,嵌入我们采用循环,不断查找下一个字母是否存在于树中,如果不存在,就新建一个子节点,如果存在在最后的那个节点处将其isEnd给设置为true。
public void insert(String word) {
Trie node = this;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
int index = c - 'a';
if(node.children[index] == null){
node.children[index] = new Trie();
}
node = node.children[index];
}
node.isEnd = true;
}
接着就是搜索前缀,其方法和前面的大致一样,不断检查前缀中的字母,如果为空,返回的就是null,如果不为空,查到前缀的最后一个字母并返回该节点。
private Trie searchPrefix(String prefix){
Trie node = this;
for (int i = 0; i < prefix.length(); i++) {
char ch = prefix.charAt(i);
int index = ch - 'a';
if(node.children[index] == null){
return null;
}
node = node.children[index];
}
return node;
}
接着就可以判断返回的是不是null,如果是,那么输入的前缀不存在于该前缀树中:
public boolean startsWith(String prefix) {
if(searchPrefix(prefix) != null){
return true;
}
return false;
}
最后就是判断单词是不是存在于前缀树中,还是利用查询前缀的方式,但这里不仅要求返回的节点不为null,同时返回的这个节点是单词的结尾节点,即isEnd=true。
public boolean startsWith(String prefix) {
if(searchPrefix(prefix) != null){
return true;
}
return false;
}
2、最大的正方形
//在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。
//
//
//
// 示例 1:
//
//
//输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”]
//,[“1”,“0”,“0”,“1”,“0”]]
//输出:4
//
//
// 示例 2:
//
//
//输入:matrix = [[“0”,“1”],[“1”,“0”]]
//输出:1
//
//
// 示例 3:
//
//
//输入:matrix = [[“0”]]
//输出:0
//
//
//
//
// 提示:
//
//
// m == matrix.length
// n == matrix[i].length
// 1 <= m, n <= 300
// matrix[i][j] 为 ‘0’ 或 ‘1’
//
// Related Topics 数组 动态规划 矩阵
public int maximalSquare(char[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int[][] ints = new int[m][n];
for (int i = 0; i < m; i++) {
ints[i][0] = matrix[i][0] - '0';
}
for (int j = 0; j < n; j++) {
ints[0][j] = matrix[0][j] - '0';
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if(matrix[i][j] == '0'){
ints[i][j] = 0;
}else{
if(ints[i-1][j] == 0 || ints[i][j-1] == 0){
ints[i][j] = 1;
}else if(ints[i-1][j] != ints[i][j-1]){
ints[i][j] = Math.min(ints[i-1][j], ints[i][j-1]) + 1;
}else{
if(ints[i-ints[i-1][j]][j-ints[i-1][j]] != 0){
ints[i][j] = ints[i-1][j]+1;
}else{
ints[i][j] = ints[i-1][j];
}
}
}
}
}
int max = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if(ints[i][j] > max){
max = ints[i][j];
}
}
}
return max*max;
}