Java 未知大小的字典-查找字典中是否有单词

Java 未知大小的字典-查找字典中是否有单词,java,algorithm,Java,Algorithm,这里有一个有趣的问题 给定字典的接口。它的大小、分布和内容未知。按升序排序 我们也只有一种方法 String getWord(long index) throws IndexOutOfBoundsException 向API添加一个方法: boolean索引(字符串字) 解决此问题的最佳实现是什么。让我们假设您的假设数据结构及其单一方法String getWord(long index)基于一个实现以下功能的字典: 向集合中添加对 从集合中删除对 修改现有对的值 查找与特定键关联的值 但是

这里有一个有趣的问题

给定字典的接口。它的大小、分布和内容未知。按升序排序

我们也只有一种方法

String getWord(long index) throws IndexOutOfBoundsException
向API添加一个方法:

boolean索引(字符串字)


解决此问题的最佳实现是什么。

让我们假设您的假设数据结构及其单一方法
String getWord(long index)
基于一个实现以下功能的字典:

  • 向集合中添加对
  • 从集合中删除对
  • 修改现有对的值
  • 查找与特定键关联的值
但是除了最后一个,所有的方法都对你隐藏了

如果是这种情况,那么您的代码肯定是不正确的,因为没有理由假设字典以任何特定顺序存储值,因此您使用
word.compareTo()
对项目进行的二进制搜索无法正常工作


此外,对于介于字典大小和
len
之间的索引号,您没有
catch
代码,您发现二的幂大于字典大小,字典大小不需要是二的幂,因此即使您更改为线性搜索而不是二进制搜索,对于不在字典中的单词,您将有一个未处理的异常。

不,字典中的单词可能没有排序。因此,你必须反复阅读字典,检查每个单词是否是你要查找的单词


如果对其进行排序,则您的解决方案可以得到改进。第一个循环只需找出单词后最右边的词条即可,您正在搜索。

duedl0r是正确的,您不能假设字典将被订购

没有任何其他信息,可能随机搜索是您可以选择的最佳算法(在估计大小后或在估计过程中)

为了正确起见,在算法的第二部分中,您应该检查异常并处理它们,因为正如您在评论中所说的,您的估计值只是一个上限,在getWord过程中,您可能会捕捉到一个

编辑:只是为了给出更好的解释
未排序列表中的搜索的时间复杂度下限等于O(n)
复杂度等于O(k),其中k是搜索中的迭代次数。所以,你可以决定k。但重要的是要理解随机搜索并不能保证成功

当n(字典的大小)非常大时,可以将k设置为比n低一些的阶数,并且很有可能找到单词

 boolean isWordInTheDictionary(String word){
    if (word == null){
        return false;
    }
    // estimate the length of the dictionary array
    long len=2;
    String temp= getWord(len);

    while(true){
        len = len * 2;
        try{
          temp = getWord(len);
        }catch(IndexOutOfBoundsException e){
           // found upped bound break from loop
           break;
        }
    }

    // Do a modified binary search using the estimated length
    long beg = 0 ;
    long end = len;
    String tempWrd;
    while(true){
        System.out.println(String.format("beg: %s, end=%s, (beg+end)/2=%s ", beg,end,(beg+end)/2));
        if(end - beg <= 1){
            return false;
        }
        long idx = (beg+end)/2;
        tempWrd = getWord(idx);
        if(tempWrd == null){
            end=idx;
            continue;
        }
        if ( word.compareTo(tempWrd) > 0){
            beg = idx;
        }
        else if(word.compareTo(tempWrd) < 0){
            end= idx;
        }else{
            // found the word..
            System.out.println(String.format("getword at index: %s, =%s", idx,getWord(idx)));
            return true;
        }
    }
}
boolean-isWordInTheDictionary(字符串字){
if(word==null){
返回false;
}
//估计字典数组的长度
长透镜=2;
字符串temp=getWord(len);
while(true){
len=len*2;
试一试{
temp=getWord(len);
}catch(IndexOutOfBoundsException e){
//从循环中找到上界中断
打破
}
}
//使用估计的长度执行修改的二进制搜索
长beg=0;
长端=透镜;
字符串tempWrd;
while(true){
System.out.println(String.format(“beg:%s,end=%s,(beg+end)/2=%s”,beg,end,(beg+end)/2));
如果(结束-0){
beg=idx;
}
else if(字比较(tempWrd)<0){
end=idx;
}否则{
//找到了这个词。。
System.out.println(String.format(“索引处的getword:%s,=%s”,idx,getword(idx));
返回true;
}
}
}

让我知道这是否正确

字典是按升序排序的-忘了补充不,不是,你误读了问题,第二句清楚地说“内容不知道,按升序排序”如我在帖子中建议的那样:你不必知道确切的上限。只要
temp
低于
word
,您只需将
len
变量加倍。我不是在快速找到确切的上限,而是一个近似的上限。