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

Finding an element in partially sorted array

提问人:YAKOVM 提问时间:6/4/2011 最后编辑:YAKOVM 更新时间:6/14/2014 访问量:1733

问:

我有一个以下面试问题。

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

以下是我对此的看法:

你应该去行 n/2.然后开始比较,例如,你搜索 100,你看到的第一个数字是 110,所以你知道它要么在这一行,要么在上面的行中,现在你去 n/4,依此类推。

从评论

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

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

C++ 数组 算法

评论

9赞 hammar 6/4/2011
对我来说听起来是正确的。O(log n) 减少到两个候选行,O(n) 在其中一个行中查找元素。这是 O(n) 总数。
0赞 sverre 6/4/2011
你不能比排序数组中的二进制搜索做得更好,你不能比未排序数组中的线性搜索做得更好,所以这对我来说似乎是最佳的。
1赞 TheFogger 6/4/2011
是正确的。二元搜索,然后是线性搜索。你不会比 O(n) 更好,因为有未排序的行。
1赞 Martin Matysiak 6/4/2011
总共不是O(n * log n)吗?他必须解析他每次二进制搜索到达的每一行,因此线性搜索的数量乘以他必须平均扫描的行数。
0赞 YAKOVM 6/4/2011
我认为马丁是对的,有人有想法去做吗?

答:

15赞 davin 6/4/2011 #1

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

O(n)溶液:

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

如果我们的值超出此范围,则继续以二进制搜索方式,选择我们的值是否小于该范围,如果值大于该值,则选择行,并再次与相邻行的一个元素进行比较。n/43n/4

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

总共.O(log n) + O(n) = O(n)

评论

0赞 dcn 6/4/2011
实际上,通过搜索行并与行的第一个(或任何)值进行比较,您可以将可能的行限制为 2 而不是 3。
0赞 davin 6/4/2011
@dcn,不是真的。 搜索任何一个都会产生目标确实在范围内,但要找到我需要搜索所有 3 行的值,如果我不这样做,我不会找到其中一个值。{ 1 2 3 ; 4 5 6 ; 8 7 9 }{2,5,7}[1,8]
0赞 dcn 6/4/2011
不。搜索“2”。与“5”相比,它更大 -> 只能在第 1 行和第 2 行。同样的论点也适用于搜索 5 和 7。
0赞 dcn 6/4/2011
我的错。我以为您正在与连续行中的元素进行比较,但是再读一遍,上一个和下一个不应该是邻居。
2赞 dcn 6/4/2011
当然,您可以将其减少到 2 个可能的行,如下所示:通过 binsearch,您可以找到行的最小索引 maxrow ,这样 maxrow 的第一个元素就比您要查找的元素大。那么只有 maxrowmaxrow-1 是候选者
3赞 dcn 6/4/2011 #2

这是一个简单的实现 - 由于我们需要 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);
            }
        }
    }
}

评论

0赞 j_random_hacker 6/5/2011
起初我很困惑你为什么在行中使用线性搜索,但后来一分钱掉了......O(n) + O(n) = O(log n) + O(n) = O(n),所以如果你不需要,为什么要花哨!:)(当然,如果它是一个 m*n 矩阵,那么为了实现最佳,你毕竟需要二进制搜索......
0赞 Neel 5/10/2013
@dcn - 您能解释一下 minrow 和 maxrow 计算背后的逻辑吗?