我正在实施有效的算法来搜索最后一次出现的事件(密钥或最近的匹配(上限))。
到目前为止,我得到了这个。
long bin_search_closest_match_last_occurance ( long * lArray, long sizeArray, long lnumber)
{
long left, right, mid, last_occur;
left = 0;
right = sizeArray - 1;
last_occur = -1;
while ( left <= right )
{
mid = ( left + right ) / 2;
if ( lArray[mid] == lnumber )
{
last_occur = mid;
left = mid +1;
}
if ( lArray[mid] > lnumber )
right = mid - 1;
else
left = mid + 1;
}
return last_occur!=-1?last_occur:mid;
}
我们有一个数组{0,0,1,5,9,9,9,9}
,关键是6
Fce应返回索引7
,但我的fce返回4
请注意,我不想线性迭代到最后一个匹配的索引。
记住我有解决方案,其中我更改参数fce(添加开始,结束索引)并使用fce从找到的上限到数组末尾执行另一个二进制搜索(仅当我找不到完全匹配时,{{1} })。
我想询问是否有更好/更清洁的解决方案来实施它?
答案 0 :(得分:0)
nm的2-search方法将起作用,并且它保持最佳的时间复杂度,但是如果你开始第二次搜索,它可能会将常数因子增加大约2或大约1.5从第一次搜索结束的地方开始。
如果你选择&#34;普通&#34;二进制搜索,找到lnumber
的第一个实例(或者,如果它不存在,则为下限),并对其进行更改,以便算法在逻辑上反转&#34; #34;通过将每个数组访问lArray[x]
更改为lArray[sizeArray - 1 - x]
(对于任何表达式x
),以及&#34;反向&#34;通过将> lnumber
测试更改为< lnumber
来排序,然后仅需要单个二进制搜索。这个算法实际执行的唯一数组访问是对lArray[mid]
的两次查找,如果它可以证明没有任何东西会改变访问之间的值,那么优化编译器很可能只评估一次(这可能需要添加{{} 3}}到long * lArray
的声明;或者,您可以将元素加载到局部变量中并测试它两次)。无论哪种方式,如果每次迭代只需要一次数组查找,那么将索引从mid
更改为sizeArray - 1 - mid
每次迭代只会增加2次额外减法(如果--sizeArray
之前只增加1次进入循环),我预计它不会像nm的方法那样增加常数。当然,和任何事情一样,如果表现至关重要,那就要测试一下;如果不是,那么就不要太担心保存微秒。
你还需要&#34;反向&#34;返回值也是:
return last_occur!=-1?last_occur:sizeArray - 1 - mid;