搜索时间复杂度较低的数组

时间:2017-08-01 16:49:33

标签: java arrays algorithm search time-complexity

向所有程序员致以问候!

我想提出我的方法来搜索一个没有时间复杂度的未排序数组(整数/字符串)。线性搜索方法通常用于具有最差情况时间复杂度O(n)的未排序数组。

我修改了线性搜索条件,还检查了数组的最后一个元素,从而减少了迭代次数。请查看此代码并提供宝贵的反馈。这是在O(n / 2)中搜索循环的最坏情况时间复杂度。 [编辑 - 通过答案,得知它仍然是O(n)]

for(int i=0, len=arr.length; i<len; i++){
        if(arr[i].equals(somethingToFind) || arr[--len].equals(somethingToFind)){
            System.out.println("Found");
            break;
        }
    }

此外,我们可以修改if语句以包含更多条件,例如检查arr [i + 1]和arr [len-1]并将i递增2以减少迭代。仅举例来说!

我想知道上述代码与线性搜索相比是否有任何性能提升。你的想法是什么?谢谢你的回复!

编辑 - 非常感谢您的精彩回复!是的,我认为额外的条件会降低成本,但只是想澄清一下。对BigONotation和时间复杂性给出了很好的回应。谢谢! : - )

5 个答案:

答案 0 :(得分:3)

完整的未知结构中搜索时,我们的效果不如线性搜索。底线是:我们需要查看每个元素以找到特定元素(产生O(n))。

如果我们从从左到右或从从右到左从两侧或甚至进行搜索都没关系随机职位。如果我们对结构没有知识而不是无关紧要

但是,如果我们知道某些,例如结构已经排序或任何其他类型的特殊分布,那么我们可以利用利用 / strong>它。

这是我们开发能够产生更好复杂性的技术的唯一情况,例如已排序结构的二进制搜索

它认为,只要你不限制输入的结构(所以允许每个任意输入结构),你总能找到一种特殊的输入,产生{{1} },用于每个算法。

如果我说得对,那么你的特殊算法会从两边处理列表,所以从左边开始一个线性搜索,从右边开始一个线性搜索,最后在中间相遇。

对于这种特殊算法,您可以生成输入,其中所需元素完全位于中间,然后您再次n-lookups

此时我认为您可能会对Big-O-Notation的特征感到困惑。

如果您在一次迭代中进行两次比较甚至100次,那么您将不会减少时间复杂度。虽然最终您的算法只有n-lookups次迭代是正确的(因为它在一次迭代中进行了2次查找),但它将再次产生n/2

并且还要注意,即使你的算法真的只是看看n-lookups元素,那么根据定义,它也会再次出现在n/2的集合中(你可以忘记所有常数因素)比如O-notation中的O(n)

正如粗略概述:在集1/2中,所有函数O(g(x))都为f(x),其中f(x) <= C * g(x)是一个任意常量。如果它不适用于所有C值,但它最多存在一个绑定的x,它适用于所有x'

例如,这些函数全部在x > x'

  • O(n)
  • 100 * n
  • 1/200 * n
  • 5 + 6n

答案 1 :(得分:1)

正如@Kayaman评论的那样,搜索未排序的数组总是O(n)

这个问题的答案有一个证明:Array search NP complete

假设你的algoritmn,你加倍了数组的大小。您还需要多长时间?加倍的时间。这就是O(n)的意思。

答案 2 :(得分:0)

假设你写

if(arr[0].equals(somethingToFind) || arr[1].equals(somethingToFind) || arr[2].equals(somethingToFind) || arr[3].equals(somethingToFind) || arr[4].equals(somethingToFind)){
            System.out.println("Found");
            break;
       }

在最坏的情况下,您的目标位于最后一个索引中。因此它将是O(n)。

答案 3 :(得分:0)

即使您在一个IF中放入2个条件,您每次迭代也会访问该阵列2次。同样在渐近符号中,O(n / 2)仍然等于O(n)。 因此,在搜索未排序数组中的元素时,您无法获得比O(n)更好的结果。

答案 4 :(得分:0)

你正在做什么(在不知不觉中)被称为循环展开,即复制循环体内的指令以减少迭代次数和循环开销。

在这种情况下,你所做的完全适得其反,有两个原因:

  • 你用一个循环退出测试来换取快捷方式 - 或者,可能有点难以进行分支预测。

  • 您在两个地方而不是一个地方扫描内存,而另一个则反向扫描内存。这是缓存不友好的。

正如其他人所说,在最坏的情况下,不可能在少于N次的比较中执行此查找。 (最坏的情况发生在搜索的元素不在列表中时。)