zoukankan      html  css  js  c++  java
  • 【算法】二分查找

    概念


       二分查找的对象必须是一个有序的数据集合,这有点类似于分治思想。每次都是通过和区间中间的元素进行比较,然后根据规则将查找区间缩小为原先的一半,直到找到需要查找的元素。由于每一次我们都是向数据集合的大小缩小为一半,因此二分查找的时间复杂度为O(nlog n)。相对于遍历查找时间效率高出很多(当然这只是在数据集合比较大的时候(内存能装下),当数据集合较小的时候,遍历查找和二分查找的速率差别不是很大)。

    实现代码



    1
    def divided_find(nums, tar): 2 if len(nums) < 1: # 数组为空直接返回 3 return 0 4 start , end = 0, len(nums)-1 5 6 while start <= end: # 循环判断条件 7 mid = start + ((end-start)>>1) # 取中间的元素 8 if nums[mid] == tar: # 如果直接相等的话直接返回结果 9 return True 10 elif nums[mid] > tar: # 中间元素大于tar,则end提前 11 end = mid - 1 12 else: 13 start = mid + 1 14 return False # 查找不到,返回False

        注意:1)循环退出条件(start <= end, 不能写成 start < end)。2)mid的求值我们使用了mid = start + ((end-start)>>1) 而没有使用常规的(start + end)//2 ,因为(start+ end) 有可能会存在溢出的情况,所以选择另一种办法,还有就是使用>> 来代表除法,加快运算效率。3)每次缩小时,都是使用mid- 1 or mid +1 , 因为如果使用start = mid 之类的话,会导致死循环。

    几个关于二分查找经典的问题


      一、查找第一个值等于给定值的元素。(在有序的数组中存在重复的值,查找给定元素值第一个出现的位置)

        解决代码(思路主要是和前面得一样,但是因为是求第一个出现的位置,所以当nums[mid]等于tart时,需要进行判断以下):

     1 def divided_find(nums, tar):
     2     if len(nums) < 1:
     3         return 0
     4     start, end = 0, len(nums)-1 
     5     while start <= end: 
     6         mid = start + ((end-start)>>1)
     7         if nums[mid] > tar:               
     8             end = mid -1
     9         elif nums[mid] < tar:
    10             start = mid + 1
    11         else:
    12             if mid == 0 or nums[mid-1] != tar:          # 改变的地方,如果mid等于0的话,直接返回。 否则判断该数字前面位置是否相等。
    13                 return mid
    14             end = mid-1
    15     return False

      二、查找最后一个值等于给定值的元素。(在有序的数组中存在重复的值,查找给定元素值最后一个出现的位置)

        解决代码(思路主要是和前面得一样,但是因为是求最后一个出现的位置,所以当nums[mid]等于tart时,需要进行判断以下):

     1 def divided_find(nums, tar):
     2     if len(nums) < 1:
     3         return 0
     4     start, end = 0, len(nums)-1
     5     while start <= end:
     6         mid = start + ((end-start)>>1)
     7         if nums[mid] > tar:
     8             end = mid -1
     9         elif nums[mid] < tar:
    10             start = mid + 1
    11         else:
    12             if mid == end or nums[mid+1 ] != tar:
    13                 return mid
    14             start = mid + 1
    15     return False

      三、查找第一个值大于等于给定值的元素。(在有序的数组中存在重复的值,查找给定元素第一个值大于等于出现的位置)

        解决代码:

     1 def divided_find(nums, tar):
     2     if len(nums) < 1:
     3         return 0
     4     start, end = 0, len(nums)-1
     5     while start <= end:
     6         mid = start + ((end-start)>>1)
     7 
     8         if nums[mid] >= tar:                    # 当元素大于或者等于目标元素时,我们对其进行判断。
     9             if mid == 0 or nums[mid-1] < tar:
    10                 return mid
    11             end = mid - 1
    12         else:
    13             start = mid + 1
    14     return False

      三、查找最后一个值小于等于给定值的元素。(在有序的数组中存在重复的值,查找给定元素最后一个值小于等于出现的位置)

        解决代码:

     1 def divided_find(nums, tar):
     2     if len(nums) < 1:
     3         return 0
     4     start, end = 0, len(nums)-1
     5     while start <= end:
     6         mid = start + ((end-start)>>1)
     7 
     8         if nums[mid] <= tar:
     9             if mid == end or nums[mid+1] > tar:
    10                 return mid
    11             start = mid + 1
    12         else:
    13             end = mid - 1
    14     return False
  • 相关阅读:
    Entity Framework 博客园专题
    部分视图调用方法总结(Action 、 RenderAction 、 Partial 、 RenderPartial)
    vs2010下安装asp.net MVC3顺序
    _viewstart.cshtml的作用
    c# yyyyMMdd,dd/MM/yyyy 类型字符串转换为datetime 类型
    c# datetime用法总结
    SQL中的每一张表都必须设有主键吗
    数据库到底用不用外键
    mysql 数据库数据迁移 The user specified as a definer ('root'@'%') does not exist 解决方法
    项目--解决MySQL数据库插入中文乱码
  • 原文地址:https://www.cnblogs.com/GoodRnne/p/10643024.html
Copyright © 2011-2022 走看看