这个问题的前提是一个排序的字符串数组,这些字符串以空字符串散布(没有特别的顺序),如下所示:
[" at","","",""," ball",& #34;"]
我的算法归结为找到中点,并且任意地向左(或向右)运行我的指针,直到它落在非空字符串上,以便我可以执行二进制搜索。
解决方案建议检查左右元素,直到我们落在非空字符串上。一旦我们有一个非空字符串,我们就可以进行二进制搜索了。
平均解决方案在非空字符串上的播放速度要快得多,但需要更多计算才能实现。因此,我很难比较/对比每种方法的时间成本。
哪种方法更优化?
答案 0 :(得分:0)
我想问题是:当你登陆一个空字符串时,什么算法会访问更少的元素?
假设您有一系列N
个空字符串。使用建议的方法,如果您登陆N/2
,您将在找到非空字符串之前访问N
个元素。
如果您考虑降落在以下位置,对于每个位置,您最终会访问两个较少的元素(一个在左边,一个在右边)。因此,作为着陆位置函数的访问元素数量为:
{2, ... N-4, N-2, N, N-2, N-4, ...}
。
如果只访问某个方向的元素,那么作为位置函数的元素数量为{N,N-1,N-2 ... 1} 假设在空字符串范围内任何位置着陆的概率是相同的,知道第一个K数的总和是
K*(K+1)
sum(1,K) = ------
2
并且前K个数的平均值是
K*(K+1)
avg(1,K) = ------ = K/2 + 1
2*K
第一种情况的平均值为2 * ((N/2)/2 + 1)
= N/2 + 2
第二种情况的平均值为N/2 + 1
因此,在复杂性方面,我认为这两种方法是相同的。
答案 1 :(得分:0)
即使使用空字符串,也可以继续进行二进制搜索。就在你遇到一个空字符串时,你应该在任意一个边上继续二进制搜索,并将其保存在堆栈中,这是随机方向或明智的方向。如果在某个时刻,算法理解它是一个错误的方向,如果最后一个方向选择是随机的,那么用二分搜索测试另一个方向并更新选择的堆栈。如果它是一个正确的方向然后只是更新该堆栈并继续作为正常的二进制搜索。这可能导致O(n),但是根据空位分布,它可能具有平均值O(log n)。
答案 2 :(得分:0)
瞥一眼我会说二进制搜索的优势在于总是通过查询中心元素来切割数组以进行搜索。由于中心元素可能是间隙,因此不再可能存在间隙。所以我们想要做的是找到最接近的非缺口元素到中心。为了做到这一点,我们会左右看。
position 1 2 3 4 5 6 7 8 9 value A B _ U _ _ _ T Z
假设我们正在寻找价值B.我们触及位置5(=(1 + 9)/ 10)这是一个差距。如果算法始终是正确的,那么我们一直走到第8位,因此搜索范围限制在1-8。
另一方面,如果我们看起来正确,然后离开(等等),那么我们找到位置4,它更接近中心,搜索范围将更加受限(1-4在这个例子中)。当然,我们总能编制一个示例,其中总是看起来正确的算法效果更好(例如,在上面的示例中寻找T :-)时,但通常最好尽可能地靠近中心,这是交替左右解决方案的作用。
评论中还建议删除差距,你回答说你必须为此阅读整个数组。这是事实,但是如果你想多次搜索相同的范围,这可能是最快的方法,因为你只需要构建一次无间隙的arrray。
我们构建一个包含值和原始位置的新数组,可以使用纯二进制搜索来搜索此数组。多次搜索此数组,一次构建这个新数组将付出代价。
position 1 2 3 4 5 orig. pos. 1 2 4 8 9 value A B U T Z