您的位置:首页 > 其它

二分查找及简单应用

2017-09-12 15:08 381 查看

二分查找

又称折半查找。

优点:是比较次数少,查找速度快,平均性能好。

缺点:是要求待查表为有序表,且插入删除困难。

适用于不经常变动而查找频繁的有序列表。

过程:首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

def BinarySearch(key, lst):
lo = 0
hi = len(lst) - 1
while lo <= hi:
mid = lo + (hi - lo)/2
if lst[mid] > key:
hi = mid - 1
elif lst[mid] < key:
lo = mid + 1
else:
return mid
return -1


简单应用

题目:找出一个序列(N个数)中三个相加和等于0的数,并打印。

方法一:三层for循环——运行时间的增长数量级为立方级别:N3

def ThreeSum(l):
N = len(l)
results = []
for i in xrange(N):
for j in xrange(i+1, N):
for k in xrange(j+1, N):
if l[i] + l[j] + l[k] == 0:
results.append((l[i], l[j], l[k]))
return results

if __name__ == '__main__':
print ThreeSum([1,2,3,4,5,6,-3,-7,-11])

----------
输出:
[(-11, 5, 6), (-7, 1, 6), (-7, 2, 5), (-7, 3, 4), (-3, 1, 2)]


方法二:借助二分查找——运行时间的增长数量级为对数级别:N2logN

改进后的算法思想:当且仅当-(a[i]-a[j])在数组中时,才满足条件。

下面的代码会将数组排序并进行N(N-1)/2次二分查找,每次查找所需要的时间都和logN成正比。因此,总的运行时间和N2logN成正比。这个解法也使我们能够解决更大规模的问题。

def BinarySearch(key, lst):
lo = 0
hi = len(lst) - 1
while lo <= hi:
mid = lo + (hi - lo)/2
if lst[mid] > key:
hi = mid - 1
elif lst[mid] < key:
lo = mid + 1
else:
return mid
return

def sum_3(l, BinarySearch):
l = sorted(l)#先排序
N = len(l)
results = []
for i in xrange(N):
for j in xrange(i+1, N):
if BinarySearch(-l[i]-l[j], l) > j:
results.append((l[i], l[j], -l[i]-l[j]))
return results

if __name__ == '__main__':
print sum_3([1,2,3,4,5,6,-3,-7,-11], BinarySearch)

----------
输出:
[(-11, 5, 6), (-7, 1, 6), (-7, 2, 5), (-7, 3, 4), (-3, 1, 2)]


目前数据规模较小,体现不出方法二的时间优势。接下来,我们再做一个测试,观察效果:

import time

def ThreeSum(l):
N = len(l)
results = []
for i in xrange(N):
for j in xrange(i+1, N):
for k in xrange(j+1, N):
if l[i] + l[j] + l[k] == 0:
results.append((l[i], l[j], l[k]))
return results

def BinarySearch(key, lst):
lo = 0
hi = len(lst) - 1
while lo <= hi:
mid = lo + (hi - lo)/2
if lst[mid] > key:
hi = mid - 1
elif lst[mid] < key:
lo = mid + 1
else:
return mid
return

def sum_3(l, BinarySearch):
l = sorted(l)#先排序
N = len(l)
results = []
for i in xrange(N):
for j in xrange(i+1, N):
if BinarySearch(-l[i]-l[j], l) > j:
results.append((l[i], l[j], -l[i]-l[j]))
return results

if __name__ == '__main__':
time_start = time.time()
sum_3([i for i in xrange(-500, 500)], BinarySearch)
time_end = time.time()
print '方法一运行时间:'+str(time_end - time_start)

time_start = time.time()
ThreeSum([i for i in xrange(-500, 500)])
time_end = time.time()
print '方法二运行时间:'+str(time_end - time_start)


输出:

方法一运行时间:0.558466911316
方法二运行时间:9.34502387047
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分查找 应用