我有一个单词列表,其中包含“简单”和“复合”单词,并且希望实现一个算法,该算法打印出一个单词列表,而不包含由简单单词组成的复合单词。
Sampel输入:
chat, ever, snapchat, snap, salesperson, per, person, sales, son, whatsoever, what, so
期望的输出:
chat, ever, snap, per, sales, son, what, so
我已经写了以下内容,但是如何从这里开始接受它:
private static String[] find(String[] words) {
ArrayList<String> alist = new ArrayList<String>();
Set<String> r1 = new HashSet<String>();
for(String s: words){
alist.add(s);
}
Collections.sort(alist,new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
int count= 0;
for(int i=0;i<alist.size();i++){
String check = alist.get(i);
r1.add(check);
for(int j=i+1;j<alist.size();j++){
String temp = alist.get(j);
//System.out.println(check+" "+temp);
if(temp.contains(check) ){
alist.remove(temp);
}
}
}
System.out.println(r1.toString());
String res[] = new String[r1.size()];
for(String i:words){
if(r1.contains(i)){
res[count++] = i;
}
}
return res;
}
任何有关更好方法的指导/见解或建议都将受到赞赏。
答案 0 :(得分:2)
我试图通过你的代码,看起来像“儿子”不在你的输出中。我相信它因为这条线而失败了:
if(temp.contains(check)) { <-- wrong check.
alist.remove(temp);
}
因此,不应只是检查temp.contains(check),而应该有一个小循环来执行以下操作:
check
开始临时?另一个实现是设置trie(https://en.wikipedia.org/wiki/Trie)并使用它进行检查?
步骤1确保当你检查一个复合词时,它的简单词已经在trie中。
答案 1 :(得分:1)
这是我直截了当的n ^ 2解决方案:
static String[] simpleWords(String[] words) {
String[] result;
HashSet<Integer> map = new HashSet<>();
for(int i = 0; i < words.length; i++) {
String word = words[i];
for(int j = 0; j < words.length; j++) {
if(j != i) {
word = word.replaceAll(words[j], "");
}
}
if(!word.equals("")) {
map.add(i);
}
}
result = new String[map.size()];
int i = 0;
for(int index: map) {
result[i] = words[index];
i++;
}
return result;
}
答案 2 :(得分:0)
我没有尝试在您的代码中找到错误,而是使用简单的循环和递归辅助方法编写自己的impl:
private static String[] find(String[] array) {
Set<String> words = new LinkedHashSet<>(Arrays.asList(array));
Set<String> otherWords = new HashSet<>(words);
for (Iterator<String> i = words.iterator(); i.hasNext(); ) {
String next = i.next();
otherWords.remove(next);
if (isCompound(next, otherWords)) {
i.remove();
} else {
otherWords.add(next);
}
}
return words.stream().toArray(String[]::new);
}
private static boolean isCompound(String string, Set<String> otherWords) {
if (otherWords.contains(string)) {
return true;
}
for (String word : otherWords) {
if (string.startsWith(word)) {
return isCompound(string.replaceAll("^" + word, ""), otherWords);
}
if (string.endsWith(word)) {
return isCompound(string.replaceAll(word + "$", ""), otherWords);
}
}
return false;
}
请参阅live demo。
这会产生您想要的输出,这需要保留字序。
复合词仅由列表中的其他词组成。重要的是,这意味着复合词以其他词开始和结束。我们可以使用这个事实来检查开始/结束,而不是在单词中的每个位置搜索其他单词,这大大简化了代码。
因此:对于列表中的每个单词,如果它以另一个单词开头/结尾,则删除该单词并重复该过程,直到没有任何内容为止,此时您知道单词是复合词。
一组“其他单词”,即删除了当前单词的完整集,将传递给辅助方法以进一步简化代码。