在部分排序的数组中查找元素

时间:2011-06-04 09:19:42

标签: c++ arrays algorithm

我有一个以下的面试问题。

有一系列nxn元素。数组是部分排序的,即行i中的最大元素小于行i+1中的最小元素。 如何找到复杂度为O(n)

的给定元素

以下是我对此的看法:

你应该去n / 2行。并开始比较,例如你搜索100,你看到的第一个数字是110,所以你知道它在这一行或上面的行中现在你去n / 4所以上。

来自评论

  

总共不是O(n * log n)吗?他有   解析他的每一行   因此,达到每个二进制搜索   线性搜索的数量是   乘以他的行数   必须平均扫描。 - 马丁   Matysiak 5分钟前。

我不确定这是一个正确的解决方案。有没有人有更好的东西

2 个答案:

答案 0 :(得分:14)

您的解决方案确实需要O(n log n),假设您正在搜索您解析的每一行。如果不搜索每一行,则无法准确执行二进制步骤。

O(n)解决方案:

选择n/2行,而不是搜索整行,我们只需要获取前一行的第一个元素,以及下一行的第一个元素。 O(1)
我们知道n/2行的所有元素必须在这些选定值之间(这是关键观察)。如果我们的目标值位于区间中,则搜索所有三行(3*O(n) = O(n))。

如果我们的值超出此范围,则继续采用二进制搜索方式,如果我们的值小于范围则选择n/4,如果值更大则选择3n/4行,并再次比较对着相邻行的一个元素。

找到3行的正确块会花费O(1) * O(log n),找到该元素将花费O(n)

总计O(log n) + O(n) = O(n)

答案 1 :(得分:3)

这是一个简单的实现 - 因为无论如何我们需要 O(n)来查找行中的元素,我省略了bin-search ......

void search(int n[][], int el) {
    int minrow = 0, maxrow;
    while (minrow < n.length && el >= n[minrow][0])
        ++minrow;
    minrow = Math.max(0, minrow - 1);
    maxrow = Math.min(n.length - 1, minrow + 1);
    for (int row = minrow; row <= maxrow; ++row) {
        for (int col = 0; col < n[row].length; ++col) {
            if (n[row][col] == el) {
                System.out.printf("found at %d,%d\n", row, col);
            }
        }
    }
}