仅使用通过索引获得单词的方法在未知大小的字典中查找单词
||
几天前,我在某大公司接受了面试,名字不是必需的:),面试官让我找到下一个任务的解决方案:
预定义:
有未指定大小的单词字典,我们只知道字典中的所有单词都已排序(例如,按字母排序)。而且我们只有一种方法
String getWord(int index) throws IndexOutOfBoundsException
需求:
需要开发使用Java在字典中查找某些输入单词的算法。为此,我们应该实现方法
public boolean isWordInTheDictionary(String word)
局限性:
我们无法更改字典的内部结构,我们无法访问内部结构,我们不知道字典中元素的数量。
问题:
我已经开发了修改后的二进制搜索,并将发布算法的变体(工作变体),但是还有其他具有对数复杂度的变体吗?我的变体的复杂度为O(logN)。
我的实现变体:
public class Dictionary {
private static final int BIGGEST_TOP_MASK = 0xF00000;
private static final int LESS_TOP_MASK = 0x0F0000;
private static final int FULL_MASK = 0xFFFFFF;
private String[] data;
private static final int STEP = 100; // for real test step should be Integer.MAX_VALUE
private int shiftIndex = -1;
private static final int LESS_MASK = 0x0000FF;
private static final int BIG_MASK = 0x00FF00;
public Dictionary() {
data = getData();
}
String getWord(int index) throws IndexOutOfBoundsException {
return data[index];
}
public String[] getData() {
return new String[]{\"a\", \"aaaa\", \"asss\", \"az\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"test\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\"};
}
public boolean isWordInTheDictionary(String word) {
boolean isFound = false;
int constantIndex = STEP; // predefined step
int flag = 0;
int i = 0;
while (true) {
i++;
if (flag == FULL_MASK) {
System.out.println(\"Word is not found ... Steps \" + i);
break;
}
try {
String data = getWord(constantIndex);
if (null != data) {
int compareResult = word.compareTo(data);
if (compareResult > 0) {
if ((flag & LESS_MASK) == LESS_MASK) {
constantIndex = prepareIndex(false, constantIndex);
if (shiftIndex == 1)
flag |= BIGGEST_TOP_MASK;
} else {
constantIndex = constantIndex * 2;
}
flag |= BIG_MASK;
} else if (compareResult < 0) {
if ((flag & BIG_MASK) == BIG_MASK) {
constantIndex = prepareIndex(true, constantIndex);
if (shiftIndex == 1)
flag |= LESS_TOP_MASK;
} else {
constantIndex = constantIndex / 2;
}
flag |= LESS_MASK;
} else {
// YES!!! We found word.
isFound = true;
System.out.println(\"Steps \" + i);
break;
}
}
} catch (IndexOutOfBoundsException e) {
if (flag > 0) {
constantIndex = prepareIndex(true, constantIndex);
flag |= LESS_MASK;
} else constantIndex = constantIndex / 2;
}
}
return isFound;
}
private int prepareIndex(boolean isBiggest, int constantIndex) {
shiftIndex = (int) Math.ceil(getIndex(shiftIndex == -1 ? constantIndex : shiftIndex));
if (isBiggest)
constantIndex = constantIndex - shiftIndex;
else
constantIndex = constantIndex + shiftIndex;
return constantIndex;
}
private double getIndex(double constantIndex) {
if (constantIndex <= 1)
return 1;
return constantIndex / 2;
}
}
没有找到相关结果
已邀请:
12 个回复
翁茄口霉氖
粟痢凰副
的替代实现。如果列表中的单词之一以字符
(即Unicode 0xffff,不是合法的无效Unicode字符)开头,则失败。
更新:我对其进行了修改,因为它实现了
,因为否则Collections中的binarySearch会在如此大的列表上使用基于迭代器的搜索,这将非常慢。但是,这现在应该相当快,因为即使List伪装成尽可能大,二进制搜索也只需要进行31次迭代。 这是一个经过稍微修改的版本,它记住最小的失败索引以将其声明的大小收敛到整个字典的实际大小,从而避免了连续查找中的几乎所有异常。尽管每当字典大小发生变化时,您都需要创建一个新的ListProxy实例。
坊岔埠绵
杰黔轿缺
捅瓶啡
窃誓额
这一功能的主要好处是它易于理解。我认为,如果您的第一次猜测低于目标,可能会更有效,因为我认为您没有利用已经“搜索”的空间,但这只是快速浏览一下您的代码。由于它是为了简化而寻找数字,因此不必处理找不到目标的问题,但这很容易扩展。
坝镰补翔奋
嘘伪
炬卤遁蝎变
琳娘
抬澈帅沮
玖料萄