Arrays 具有未知项数的二进制搜索
假设您不知道正在搜索的元素的数量,并且给定了一个API,该API接受索引,如果超出了范围(在这里使用getWordFromDictionary方法实现),那么如何执行二进制搜索并为客户端程序实现IsWordIndicationary()方法 这个解决方案是可行的,但我最终在找到初始高索引值的级别上进行了一次串行搜索。通过较低范围的值进行搜索的灵感来自。我也在Reflector(C#decompiler)中查看了BinarySearch,但它有一个已知的列表长度,因此仍在寻找填补空白的方法Arrays 具有未知项数的二进制搜索,arrays,algorithm,binary-search,Arrays,Algorithm,Binary Search,假设您不知道正在搜索的元素的数量,并且给定了一个API,该API接受索引,如果超出了范围(在这里使用getWordFromDictionary方法实现),那么如何执行二进制搜索并为客户端程序实现IsWordIndicationary()方法 这个解决方案是可行的,但我最终在找到初始高索引值的级别上进行了一次串行搜索。通过较低范围的值进行搜索的灵感来自。我也在Reflector(C#decompiler)中查看了BinarySearch,但它有一个已知的列表长度,因此仍在寻找填补空白的方法 pri
private static string[] dictionary;
static void Main(string[] args)
{
dictionary = System.IO.File.ReadAllLines(@"C:\tmp\dictionary.txt");
Console.WriteLine(isWordInDictionary("aardvark", 0));
Console.WriteLine(isWordInDictionary("bee", 0));
Console.WriteLine(isWordInDictionary("zebra", 0));
Console.WriteLine(isWordInDictionaryBinary("aardvark"));
Console.WriteLine(isWordInDictionaryBinary("bee"));
Console.WriteLine(isWordInDictionaryBinary("zebra"));
Console.ReadLine();
}
static bool isWordInDictionaryBinary(string word)
{
// assume the size of the dictionary is unknown
// quick check for empty dictionary
string w = getWordFromDictionary(0);
if (w == null)
return false;
// assume that the length is very big.
int low = 0;
int hi = int.MaxValue;
while (low <= hi)
{
int mid = (low + ((hi - low) >> 1));
w = getWordFromDictionary(mid);
// If the middle element m you select at each step is outside
// the array bounds (you need a way to tell this), then limit
// the search to those elements with indexes small than m.
if (w == null)
{
hi = mid;
continue;
}
int compare = String.Compare(w, word);
if (compare == 0)
return true;
if (compare < 0)
low = mid + 1;
else
hi = mid - 1;
}
// punting on the search above the current value of hi
// to the (still unknown) upper limit
return isWordInDictionary(word, hi);
}
// serial search, works good for small number of items
static bool isWordInDictionary(string word, int startIndex)
{
// assume the size of the dictionary is unknown
int i = startIndex;
while (getWordFromDictionary(i) != null)
{
if (getWordFromDictionary(i).Equals(word, StringComparison.OrdinalIgnoreCase))
return true;
i++;
}
return false;
}
private static string getWordFromDictionary(int index)
{
try
{
return dictionary[index];
}
catch (IndexOutOfRangeException)
{
return null;
}
}
私有静态字符串[]字典;
静态void Main(字符串[]参数)
{
dictionary=System.IO.File.ReadAllLines(@“C:\tmp\dictionary.txt”);
Console.WriteLine(iswordindicationary(“aardvark”,0));
Console.WriteLine(iswordindicationary(“bee”,0));
Console.WriteLine(iswordindicationary(“zebra”,0));
控制台写入线(IsWordIndicationary(“aardvark”);
控制台。WriteLine(iswordindicationary(“bee”);
控制台。WriteLine(iswordindicationary(“斑马”);
Console.ReadLine();
}
静态bool iswordindicationBynary(字符串字)
{
//假设字典的大小未知
//快速检查空字典
字符串w=getWordFromDictionary(0);
如果(w==null)
返回false;
//假设长度非常大。
int低=0;
int hi=int.MaxValue;
而(低>1));
w=getWordFromDictionary(mid);
//如果在每个步骤中选择的中间元素m在外部
//数组边界(您需要一种方法来说明这一点),然后限制
//对索引小于m的元素的搜索。
如果(w==null)
{
高=中;
继续;
}
int compare=String.compare(w,word);
如果(比较==0)
返回true;
如果(比较<0)
低=中+1;
其他的
hi=mid-1;
}
//在hi当前值上方的搜索上下注
//达到(仍然未知)上限
返回iswordindicational(word,hi);
}
//串行搜索,适用于少量项目
静态bool iswordindicationary(字符串字,int startIndex)
{
//假设字典的大小未知
int i=起始索引;
while(getWordFromDictionary(i)!=null)
{
if(getWordFromDictionary(i).Equals(word,StringComparison.OrdinalIgnoreCase))
返回true;
i++;
}
返回false;
}
私有静态字符串getWordFromDictionary(int索引)
{
尝试
{
返回字典[索引];
}
捕获(IndexOutOfRangeException)
{
返回null;
}
}
回答后的最终代码
static bool isWordInDictionaryBinary(string word)
{
// assume the size of the dictionary is unknown
// quick check for empty dictionary
string w = getWordFromDictionary(0);
if (w == null)
return false;
// assume that the number of elements is very big
int low = 0;
int hi = int.MaxValue;
while (low <= hi)
{
int mid = (low + ((hi - low) >> 1));
w = getWordFromDictionary(mid);
// treat null the same as finding a string that comes
// after the string you are looking for
if (w == null)
{
hi = mid - 1;
continue;
}
int compare = String.Compare(w, word);
if (compare == 0)
return true;
if (compare < 0)
low = mid + 1;
else
hi = mid - 1;
}
return false;
}
static bool iswordindicationary二进制(字符串字)
{
//假设字典的大小未知
//快速检查空字典
字符串w=getWordFromDictionary(0);
如果(w==null)
返回false;
//假设元素的数量非常大
int低=0;
int hi=int.MaxValue;
而(低>1));
w=getWordFromDictionary(mid);
//将null视为查找出现的字符串
//在你要找的绳子后面
如果(w==null)
{
hi=mid-1;
继续;
}
int compare=String.compare(w,word);
如果(比较==0)
返回true;
如果(比较<0)
低=中+1;
其他的
hi=mid-1;
}
返回false;
}
因此,我不确定从您的描述中是否完全理解了这个问题,但我假设您正在尝试搜索长度未知的排序的数组以查找特定字符串。我还假设实际数组中没有空值;仅当请求超出范围的索引时,数组才会返回null
如果这些都是真的,那么解决方案应该只是一个标准的二进制搜索,尽管是在整个整数空间中搜索,并且将null视为查找所查找字符串后面的字符串。本质上,只要想象一下,N个字符串的排序数组实际上是一个INT_MAX字符串的排序数组,最后是null
我不太明白的是,您似乎已经基本上做到了这一点(至少粗略地看一下代码),因此我认为我可能无法完全理解您的问题。因此,我不确定我是否完全理解您描述的问题,但我假设您正在尝试搜索长度未知的排序的数组以查找特定字符串。我还假设实际数组中没有空值;仅当请求超出范围的索引时,数组才会返回null 如果这些都是真的,那么解决方案应该只是一个标准的二进制搜索,尽管是在整个整数空间中搜索,并且将null视为查找所查找字符串后面的字符串。本质上,只要想象一下,N个字符串的排序数组实际上是一个INT_MAX字符串的排序数组,最后是null
我不太明白的是,您似乎已经基本上做到了这一点(至少粗略地看一下代码),因此我想我可能无法完全理解您的问题。当然可以。从索引1开始,将查询索引加倍,直到找到比查询词(Edit:或null)更大的单词。然后可以再次缩小搜索空间,直到找到索引,或者返回false
编辑:请注意,这不会添加到渐进运行时,它仍然是O(logN),其中N是序列中的项数。当然可以。从索引1开始,将查询索引加倍,直到找到
bool isPresentPhase1(string word)
{
int l = 0, d = 1;
while( true ) // you should eventually reach an index out of bounds
{
w = getWord(l + d);
if( w == null )
return isPresentPhase2(word, l, l + d - 1);
int c = String.Compare(w, word);
if( c == 0 )
return true;
else if( c < 0 )
isPresentPhase2(value, l, l + d - 1);
else
{
l = d + 1;
d *= 2;
}
}
}
bool isPresentPhase2(string word, int lo, int hi)
{
// normal binary search in the interval [lo, hi]
}