题目描述:
思路:这道题和139.单词拆分 有些类似。但是动态规划的转移方程不同。要注意的几点:1.不能用boolean的动态规划矩阵。2.HashSet能丢入容器构造但是不能丢入单纯的数组。3.题目要求返回的未识别字数的数量最小,所以当当前单词包含的时候要进行判定这样包含是否返回的是最少的未识别字符数。
class Solution {
public int respace(String[] dictionary, String sentence) {
HashSet<String> hashSet=new HashSet();
int len=sentence.length();
int count=0;
int[] result=new int[len+1];
for(int i=0;i<dictionary.length;i++){
hashSet.add(dictionary[i]);
}
for(int i=1;i<=len;i++){
result[i]=result[i-1]+1;
for(int j=0;j<i;j++){
if(hashSet.contains(sentence.substring(j,i))){
result[i]=Math.min(result[i],result[j]);
}
}
}
return result[len];
}
}
执行结果:
时间复杂度很高,该如何改进?官方题解2用了字符串Hash表。(个人理解是不存放字符串,而将字符串转换为数字hashcode存放便于查找)
官方代码
class Solution {
static final long P = Integer.MAX_VALUE;
static final long BASE = 41;
public int respace(String[] dictionary, String sentence) {
Set<Long> hashValues = new HashSet<Long>();
for (String word : dictionary) {
hashValues.add(getHash(word));
}
int[] f = new int[sentence.length() + 1];
Arrays.fill(f, sentence.length());
f[0] = 0;
for (int i = 1; i <= sentence.length(); ++i) {
f[i] = f[i - 1] + 1;
long hashValue = 0;
for (int j = i; j >= 1; --j) {
int t = sentence.charAt(j - 1) - 'a' + 1;
hashValue = (hashValue * BASE + t) % P;
if (hashValues.contains(hashValue)) {
f[i] = Math.min(f[i], f[j - 1]);
}
}
}
return f[sentence.length()];
}
public long getHash(String s) {
long hashValue = 0;
for (int i = s.length() - 1; i >= 0; --i) {
hashValue = (hashValue * BASE + s.charAt(i) - 'a' + 1) % P;
}
return hashValue;
}
}
另外,官方给出的最优解法为应用字典树
代码:
class Solution {
public int respace(String[] dictionary, String sentence) {
int n = sentence.length();
Trie root = new Trie();
for (String word: dictionary) {
root.insert(word);
}
int[] dp = new int[n + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int i = 1; i <= n; ++i) {
dp[i] = dp[i - 1] + 1;
Trie curPos = root;
for (int j = i; j >= 1; --j) {
int t = sentence.charAt(j - 1) - 'a';
if (curPos.next[t] == null) {
break;
} else if (curPos.next[t].isEnd) {
dp[i] = Math.min(dp[i], dp[j - 1]);
}
if (dp[i] == 0) {
break;
}
curPos = curPos.next[t];
}
}
return dp[n];
}
}
class Trie {
public Trie[] next;
public boolean isEnd;
public Trie() {
next = new Trie[26];
isEnd = false;
}
public void insert(String s) {
Trie curPos = this;
for (int i = s.length() - 1; i >= 0; --i) {
int t = s.charAt(i) - 'a';
if (curPos.next[t] == null) {
curPos.next[t] = new Trie();
}
curPos = curPos.next[t];
}
curPos.isEnd = true;
}
}