【发布时间】:2011-09-03 15:22:44
【问题描述】:
前几天我在某大公司面试,名字不要求:),面试官让我想办法解决下一个任务:
预定义: 有一个未指定大小的单词字典,我们只知道字典中的所有单词都是排序的(例如按字母表)。我们也只有一种方法
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;
}
}
【问题讨论】:
-
二分搜索可能是最好的方法之一
-
嗯?您说您的变体具有复杂度 O(logN),这通常是在排序列表中的搜索应该是什么,并且所需的解决方案具有“对数复杂度”(意思是,我假设 O(logN)。你在找什么?
-
向字典作者抱怨他们糟糕的 API 并让他们更改它。 O(1)
-
@Seth 我正在寻找另一种算法,因为面试官告诉我我的变体很好,但还有另一个具有相同复杂性的算法。
-
@alexcoco 谢谢 :) 我知道修改后的二进制搜索是个好主意,我已经实现了它,但我正在寻找另一种解决方案。
标签: java algorithm binary-search