查找数组中指定元素的第一个出现位置

时间:2016-01-23 14:12:21

标签: arrays algorithm binary-search

假设我有一个数组A,按照这个

的非降序排列
A = [0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 500, 600]

我的问题是:如何找到元素的第一次出现(索引)等于或更大(如果不存在4)而不是4?

O(n)解决方案很简单,我希望能有更快的速度。 可能是二进制搜索,但不知道如何修改它。

3 个答案:

答案 0 :(得分:2)

这是一个略微修改的二进制搜索,用于在返回之前与之前的元素进行比较。如果存在重复,则按预期继续二进制搜索,而不是串行搜索,因此它对于排序数组的结构独立地为O(log(n))(例如,当存在多个重复项时)。它是用Java编写的。

*如果元素不存在,我返回下一个更大元素的索引,即如果必须将其放入数组中,则应插入密钥的索引。我返回一个负值作为“未找到”的指标。

* 否定未找到值的唯一例外是当键是最小且未找到时,您期望0(它没有负数)。但是,您可以轻松处理这种特殊情况,以区分发现和未找到:例如,如果Integer.MIN_VALUE则返回-(array.length + 1)-lo == 0

*如果键大于每个数组值,您希望返回一个等于数组大小的索引(再次为负值)。

public static int indexOf(int[] a, int key) {
    int lo = 0;
    int hi = a.length - 1;
    while (lo <= hi) {
        int mid = lo + (hi - lo) / 2;
        if      (key < a[mid]) hi = mid - 1;
        else if (key > a[mid]) lo = mid + 1;
        else if (mid == 0 || key != a[mid-1]) return mid;
        else hi = mid - 1; //we have a duplicate, go left
    }
    //not present; show index of next greater element
    //OR array.length if bigger than every existing element
    return -lo;
}

答案 1 :(得分:1)

标准二分查询:

left limit = left end of array
right limit = right end of array
look at middle
if middle == target: stop
else:
    set left or right to middle based on result of comparison
    loop

此变体,标有*的更改:

left limit = left end of array
right limit = right end of array
look at middle
* if limits are close together: stop
* if middle == target and limits are not close together:
*    set right to middle
*    loop
else:
    set left or right to middle based on result of comparison
    loop

这将使目标或该点的最左侧发生率为零 如果失踪,目标会去哪里。然后只是环顾四周 区域,看看要返回什么。

答案 2 :(得分:1)

以下python代码使用简单的二进制搜索算法来查找上限值。运行时间O(log(n))

def binary_search(array, target):
lower = 0
upper = len(array)
while lower < upper:
    x = lower + (upper - lower) // 2
    val = array[x]
    if target == val:
        return x
    elif target > val:
        if lower == x:
            break
        lower = x
    elif target < val:
        upper = x
return upper

# Test Array
arr = [0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 4, 4, 6, 7, 8]
print arr[binary_search(arr, 5)]