Python 中的二进制搜索

Binary Searching in Python

所以我有这个问题。

You are given a landscape in the form of a non-empty one-dimensional array seq. The goal is to find an index i of a cell that is a pit. We say seq[i] is a pit if seq[i] <= seq[i-1] and seq[i] <= seq[i+1]. For example in the array [7, 6, 9, 7, 8], the indices 1 and 3 are pits. The first or last elements are considered to be a pit if they are less than or equal to their only neighbour. For example the last element of [3, 2, 4, 4, 1] is a pit (and also index 1). Note that the definition of a pit also includes equality; for example in [3, 2, 2, 2, 5, 6, 6, 8], the indices 1, 2, 3, and 6 are pits. As a special case, we also define the only cell of an array of length one to be a pit as well.

我已经制定了一个解决方案,使用二进制搜索(某种)来实现 O(logn) 作为最坏情况的时间。但是我遇到了一个 returns 没有或 NONE.

的例子
def find_pit(seq):
    first = 0
    last = len(seq) - 1
    origlast = last
    mid = 0
    if len(seq) == 1 :
        return 0
    else:
        while first <= last & mid < last :
            mid = (first + last) // 2
            if seq[mid] <= seq[mid - 1] & seq[mid] <= seq[mid + 1]:
                return mid
            else:
                if seq[mid] > seq[mid - 1]:
                    last = mid
                else:
                    first = mid
    if seq[0] <= seq[1]:
        return 0
    elif seq[origlast] <= seq[origlast-1]:
        return (len(seq) - 1)

print(find_pit([0,1]))
print(find_pit([5, 4, 3, 6, 7]))

我该如何解决这个问题?

您需要更改

& (bitwise "and")

and (logical "and")

在您的代码中:

def find_pit(seq):
    first = 0
    last = len(seq) - 1
    origlast = last
    mid = 0
    if len(seq) == 1 :
        return 0
    else:
        #change next line to use logical and
        while first <= last and mid < last :  
            mid = (first + last) // 2
            #change next line to use logical and
            if seq[mid] <= seq[mid - 1] and seq[mid] <= seq[mid + 1]:
                return mid
            else:
                if seq[mid] > seq[mid - 1]:
                    last = mid
                else:
                    first = mid
    if seq[0] <= seq[1]:
        return 0
    elif seq[origlast] <= seq[origlast-1]:
        return (len(seq) - 1)


print(find_pit([0,1]))
print(find_pit([5, 4, 3, 6, 7]))

运行 以上测试用例现在将给出结果: 第一个列表为 0,第二个列表为 2。

似乎可以在给定的情况下找到第一个坑。我调整了调用以允许检查多个函数。

#.... original find_pit left, but not pasted in
import sys

def find_pit2(seq):

    left = sys.maxint
    maxp = len(seq)

    if maxp == 1 :
        return 0
    else:
        for pos, current in enumerate(seq):
            try:
                right = seq[pos+1]
            except IndexError:
                #rightmost, count as right neighbor as bigger
                right = sys.maxint
            #pit - smaller or equal to neighbours
            if left >= current and current <= right:
                return pos
            left = current


li_f = [find_pit, find_pit2]


for f in li_f:
    print f.__name__

    print("  ",f([0,1]))
    print("  ",f([5, 4, 3, 6, 7]))
    print("  ",f([7, 6, 9, 7, 8]))
    print("  ",f([3, 2, 2, 2, 5, 6, 6, 8]))

给予

find_pit
('  ', 0)
('  ', 2)
('  ', None)
('  ', 3)
find_pit2
('  ', 0)
('  ', 2)
('  ', 1)
('  ', 1)