9

给定一个排序的数字列表,我需要找到大于给定数字的最小数字。考虑这个列表:


arr=[1,2,3,5,7,11,101,131,151,181,191,313,353,373,383]

假设指定的数字是 320。那么,我的方法应该返回 353,因为 353 是大于 320 的最小数字。

我正在尝试使用稍微修改的二进制搜索形式;但是在执行时程序进入无限循环。


def modBinarySearch(arr,x):
    l=len(arr)
    mid=l/2
    if arr[mid]>=x and arr[mid-1]<x:
        return arr[mid]
    elif arr[mid]>x and arr[mid-1]>x:
        modBinarySearch(arr[mid:l],x)
    else: 
        modBinarySearch(arr[0:mid],x)

N=int(raw_input())
arr=[1,2,3,5,7,11,101,131,151,181,191,313,353,373,383]
print modBinarySearch(arr,N)

有人可以指出我做错了什么吗?

4

8 回答 8

11

有一个标准模块,bisect已经这样做了:

In [49]: arr[bisect.bisect(arr, 320)]
Out[49]: 353

我认为这应该是搜索排序列表的首选方法。手册中有几个例子

至于你的实现,有很多问题:

  1. 您的递归不能正确处理小数组。
  2. 在第二个分支中进行的切片不正确。
  3. 您的函数不返回任何内容。
  4. 因为arr是升序,arr[mid]>x and arr[mid-1]>x相当于arr[mid-1]>x,提示你没有写你的意思

最后但同样重要的是,对于这个问题,递归和所有切片都是完全不必要的。

于 2012-12-02T13:42:10.633 回答
6

如果列表的大小为 15,请完全放弃二进制搜索并使用顺序搜索。

您会发现代码更容易编写,除非您需要每秒执行数百万次,否则顺序解决方案将足够快。

如果您确实需要坚持使用二进制搜索,那么您的第一步应该是实际返回递归调用的结果。

于 2012-12-02T13:42:06.323 回答
5

如果 arr[mid] 和 arr[mid-1] 都大于你的数字,你应该在 arr[0:mid] 中搜索,你不觉得吗?

 elif arr[mid]>x and arr[mid-1]>x:
    modBinarySearch(arr[0:mid],x)
else: 
    modBinarySearch(arr[mid:1],x)
于 2012-12-02T13:51:08.687 回答
3
def modBinarySearch(arr, n):
    m = len(arr) / 2

    if arr[m] >= n and arr[m - 1] < n:
        return arr[m]
    elif arr[m] > n and arr[m - 1] > n:
        return modBinarySearch(arr[:m], n)
    else:
        return modBinarySearch(arr[m:], n)


arr = [1, 2, 3, 5, 7, 11, 101, 131, 151, 181, 191, 313, 353, 373, 383]
n = 320
print(modBinarySearch(arr, n))
于 2012-12-02T13:49:40.823 回答
2
     python 3.2

     next(i for  i in arr if i>320)
于 2012-12-02T13:50:02.917 回答
1

bisect 模块是您的最佳选择:

from bisect import bisect_left, bisect_right

arr=[1,2,3,5,7,11,101,131,151,181,191,313,353,373,383]


def find_lt(a, x):
    'Find rightmost value less than x'
    i = bisect_left(a, x)
    if i:
        return a[i-1]
    raise ValueError

def find_gt(a, x):
    'Find leftmost value greater than x'
    i = bisect_right(a, x)
    if i != len(a):
        return a[i]
    raise ValueError

print find_lt(arr,320)          
print find_gt(arr,320)  

印刷

313
353     
于 2012-12-03T17:32:25.883 回答
0

如果列表已排序:

x = range(20)
N= 15

for i in x:
    if i>N:
        print i
        break

给16。

如果使用 numpy:

x = np.arange(20)
N = 15
x[x>15][0]

给16。

如果您正在寻找简单的实现,对于您的具体问题,让我再谈一谈。

于 2012-12-02T13:46:15.137 回答
0
def modBinarySearch(arr,x):
    l=len(arr)
    mid=l/2
    if arr[mid] >= x and arr[mid-1] < x:
        return arr[mid]
    elif arr[mid]>x and arr[mid-1]>x:
        num = modBinarySearch(arr[0:mid],x)
    else:
        num = modBinarySearch(arr[mid:l],x)
    return num

N=int(raw_input('Enter a number: '))
arr=[1, 2, 3, 5, 7, 11, 101, 131, 151, 181, 191, 313, 353, 373, 383]
print modBinarySearch(arr,N)
于 2015-04-07T19:36:28.327 回答