如何使用二进制搜索来查找数组中的第一个非null元素?

时间:2013-05-18 10:41:31

标签: algorithm binary-search

假设我有一个连续数据和连续空值的数组,例如:

0, 3, 1, 2, null, null, null

如何使用二元搜索思想查找第一个null元素的索引?

4 个答案:

答案 0 :(得分:4)

与常规二进制搜索相同,只处理NULL值,如值无穷大(max int)和其他所有值,如值0.这样,数组看起来像

0, 0, 0, 0, MAX_INT, MAX_INT, MAX_INT

此时对其上的第一个MAX_INT运行正常二进制搜索

答案 1 :(得分:1)

按如下方式进行二元搜索:

  • 从中间开始(与二元搜索一样)
  • 当你找到一个非null,二分法搜索到右边
  • 当您找到null时,请检查左侧的元素
    • 如果是null,则左侧二进制搜索
    • 如果不是 - null(或者左边没有元素,因为我们已经在最左边的元素),我们找到了第一个null的索引

一些简单的伪代码:

int search(start, end):
  // terminating check - should always be the first null
  if start == end
    // sanity check - make sure it's correct
    assert(input[start] == null && (start == 0 || input[start-1] != null))
    return start

  mid = (start+end)/2

  if input[mid] != null
    return search(mid, end) // search right
  else if mid == 0 || input[mid-1] != null // check element to left
    return mid // found
  else
    return search(start, mid) // search left

答案 2 :(得分:0)

这是用Go编写的示例解决方案,具有O(log(n))时间复杂度:

package main

import "fmt"

func findIn(array []int) {
    fmt.Printf("%v ", array)

    if len(array) == 0 {
        fmt.Println("Not Found")
        return
    }

    for low, high, mid := 0, len(array), len(array)/2; ; {

        // terminate search when high meets mid
        if high-mid == 1 {
            if array[mid] == -1 {
                fmt.Println(mid)
                return
            }
            if high == len(array) {
                fmt.Println("Not Found")
                return
            }
            fmt.Println(high)
            return
        }

        // search lower half if middle is -1, otherwise search upper half
        if array[mid] == -1 {
            high = mid
            mid = low + (mid-low)/2
        } else {
            low = mid
            mid = mid + (high-mid)/2
        }
    }

    fmt.Println()
}

func main() {
    findIn([]int{})
    findIn([]int{8})
    findIn([]int{-1})
    findIn([]int{8, -1, -1, -1})
    findIn([]int{8, 9, 7, -1, -1, -1})
    findIn([]int{8, 9, 7, 6, 5, 4, -1, -1})
}

输出:

[] Not Found
[8] Not Found
[-1] 0
[8 -1 -1 -1] 1
[8 9 7 -1 -1 -1] 3
[8 9 7 6 5 4 -1 -1] 6

请随时提出更好/更短的解决方案。

答案 3 :(得分:0)

O(n)的简单蛮力在这里可能是理想的,因为在划分和征服集合时,它同样可能会错过第一次出现的Null。