在无限长度排序数组中查找元素

时间:2012-09-06 13:11:54

标签: performance algorithm data-structures time-complexity

给定一个具有正整数和负整数的无限长度排序数组。在其中找到一个元素。

修改
数组中的所有元素都是唯一的,并且数组在正确的方向上是无限的。

有两种方法:

方法1:

将索引设置在位置100,如果要找到的元素较少,则在前100个项目中进行二进制搜索,否则将下一个索引设置在位置200.这样,继续将索引增加100直到该项目更大。

方法2:

将索引设置为2.首先将索引设置为位置2,然后设置为4,然后设置为8,然后设置为16,依此类推。再次进行二元搜索,从位置2 ^ K到2 ^(K + 1),其中项目介于两者之间。

在最佳情况和最差情况下,这两种方法中的哪一种会更好?

7 个答案:

答案 0 :(得分:18)

第一种方法在元素的索引中是线性的(O(k),其中k是元素的索引)。实际上,您需要k/100次迭代才能找到大于搜索元素的元素,即O(k)

第二种方法将在同一索引中进行对数。 O(logk)。 (其中k是元素的索引)。在这里,您将需要log(k)次迭代,直到找到更高的元素。然后,2^(i-1)2^i(其中i是迭代次数)之间的二进制搜索也将是对数的,总计为O(logk)

因此,第二个效率更高

答案 1 :(得分:3)

如果数组是有根据的,即具有最小元素(即你有元素 x 0 x 1 ,...),并且所有元素都是唯一的,那么这是一个简单的方法:如果你正在寻找数字 n ,你可以对索引0进行二元搜索, ..., n - x 0 。请注意,我们总是有基本的不等式 x i i + x <所有 i ≥0的sub> 0 。

因此,您可以在log 2 中找到值 n n - x 0 < / sub>)步骤。

答案 2 :(得分:1)

您可以通过一些小修改直接或多或少地应用二进制搜索。这大致对应于您的方法2。

基本上,选择一些数字B并将A设置为0,然后检查您要查找的元素是否在A和B之间。如果是,则在这些边界中执行通常的二分搜索,否则设置B = A和A = 2 * A并重复。这将采用O(log(M)),其中M是您在数组中寻找的元素的位置。

答案 3 :(得分:1)

由于数组是无限的,索引必须是可变长度的。这意味着对它们进行数学运算不是O(1),这反过来意味着“首先搜索端点的二进制搜索”与O(log(k))的时间复杂度略有不同。

在搜索端点时完成的索引数学只是左移一,取O(log(k)),因为最多k的索引需要最多log(k)位并向左移位一个是位数的线性。

二进制搜索中完成的索引数学也是O(log(k))

因此两种算法的实际复杂度为O(log(k)^2)。线性搜索的复杂性为O(k log k),因此它仍然会丢失。

答案 4 :(得分:0)

只需2美分。我们有一个无限阵列因此可以想象我们正在寻找非常大的数字。你有没想过?嗯,它会变得更大。请注意,二进制搜索的间隔长度为2^i = 2^(i+1)-2^i,因此查找数字需要log(2^i)=i时间。另一方面,达到目标间隔需要i时间。因此,总时间复杂度再次为O(n)。我缺少什么?

答案 5 :(得分:0)

Here是另一个实现,它使用2 ^ n来搜索元素本身的出现,然后将该子数组赋予二进制搜索

e.g.
 arr = 1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1...........
 num = 8;

efficiency = 2logn

答案 6 :(得分:0)

-完整的解决方案-占用O(logn)时间复杂度

公共B类{

public static void main(String[] args) {
    // Assuming sorted array of infinite length
    int a[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

    int elementToFind = 12;

    int finalIndex = getFinalIndex(a, elementToFind);

    if (finalIndex == -1) {
        System.out.println("Element not found");
    }
    System.out.println("Found element:" + a[finalIndex]);

}

private static int getFinalIndex(int[] a, int elementToFind) {

    int power = 2;
    int finalIndex = (int) Math.pow(2, power);

    for (int i = 0; i < finalIndex;) {

        if (elementToFind == a[finalIndex]) {
            return finalIndex;
        }

        else if (elementToFind < a[finalIndex]) {
            System.out.println("search through binary search algo");
            // taking i as starting index in binary search call
            int searchedIndex = callToBinarySearch(a, i, finalIndex);
            return searchedIndex;
        }

        else {
            i = finalIndex + 1;
            power = power * 2;
            finalIndex = (int) Math.pow(2, power);

        }
    }
    return -1;

}

}