【问题标题】:Binary search implementations二分搜索实现
【发布时间】:2015-08-18 09:23:51
【问题描述】:

我被困在实现 5 种不同的二进制斩波方式(任务http://codekata.com/kata/kata02-karate-chop/)。您能否就更多方法提出一些想法?
这就是我所得到的:
1)

def left_chop(key, arr):
    l = 0
    r = len(arr)
    while l<r:
        m = (l+r)/2
        if key<=arr[m]:
            r = m 
        else:
            l = m+1
    return l if key == arr[l] else -1


2)

def left_chop(key, array, left = 0, right = None):
    if right == None:
        right = len(array)
    if left==right:
        return left if key == array[left] else -1
    m = (left+right)/2
    if key<=array[m]:
        return left_chop(key, array, left, m)
    else:
        return left_chop(key, array, m+1, right)


3)我知道,和第一个很像

class find(object):
    def __init__(self, key, array):
        self.array = array
        self.key = key
        self.l = 0
        self.r = len(array)

    def left_chop(self):
        while self.l<self.r:
            self.step()
        return self.l if self.key == self.array[self.l] else -1

    def step(self):
        m = (self.l+self.r)/2
        if self.key<=self.array[m]:
            self.r = m
        else:
            self.l = m+1

我曾尝试想出一些函数式编程风格的东西,但没有成功。

【问题讨论】:

  • Python 不是最适合函数式编程的语言,如果你喜欢函数式你会喜欢 scala,在纯 python 的 bisect 模块中也有二分算法
  • 谢谢,我会尝试 scala。有这样的模块,但它使用类似于第一个的方法:hg.python.org/cpython/file/2.7/Lib/bisect.py
  • 第一个不是有效的 Python。
  • 谢谢,我已经编辑了帖子。
  • 您可能会发现 Rosetta Code 网站很有用。它向您展示了多种语言和风格的算法实现。这是Binary Search 页面和Python 部分。

标签: python algorithm search


【解决方案1】:

您可以使用生成器:

def chopper(array, val):
    edges = (0, len(array))
    while True:
        m = sum(edges)/2
        edges = (edges[0], m) if array[m] >= val else (m+1, edges[1])
        yield edges

def chopSearch(array, val):
    for l, r in chopper(array, val):
        if array[l] == val:
            return l
        if l==r:
            return -1

【讨论】:

    【解决方案2】:

    4) 这个使用递归。如果中途正确,则返回索引。否则,它将数组分成两半并以这种方式继续搜索。

    def getIndexOf(search, array):
        arrlen = len(array)
        halfindex = arrlen / 2 - ((arrlen % 2) / 2)
        value = array[halfindex]
        if len(array) < 2 and array[0] != search:
            return -1;
        if value == search:
            return halfindex
        elif search < value:
            return getIndexOf(search, array[0:halfindex])
        else:
            return getIndexOf(search, array[halfindex:arrlen] + halfindex)
    

    【讨论】:

    • 我对其进行了编辑,以便在数组中不存在搜索时它不会超过最大递归深度
    • 添加if search not in array 破坏了二进制搜索背后的整个想法,不是吗?在第一次递归中,它将完整运行array...你可能想要if len(array) &lt; 2 and search != array[0]: return -1。还有一个 ) 在你的最后一行太多...
    【解决方案3】:

    1.二分查找算法的简单实现。

    def binary_search(seq, t):
    min = 0
    max = len(seq) - 1
      while True:
         if max < min:
           return -1
           m = (min + max) // 2
         if seq[m] < t:
           min = m + 1
         elseif seq[m] > t:
           max = m - 1
       else:
          return m
    
    1. 二分查找的替代方法。

      def binarySearch(alist, item):
          first = 0
          last = len(alist)-1
          found = False
      while first<=last and not found:
           midpoint = (first + last)//2
      if alist[midpoint] == item:
         found = True
       else
      if item < alist[midpoint]:
      last = midpoint-1
       else:
      first = midpoint+1
          return found
      testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
      print(binarySearch(testlist, 3))
      print(binarySearch(testlist, 13))
      

    3.python编程中处理二分查找的第三种不同方式

       def binarySearch(alist, item):
            if len(alist) == 0:
                return False
            else:
                midpoint = len(alist)//2
                if alist[midpoint]==item:
                  return True
                else:
                  if item<alist[midpoint]:
                    return binarySearch(alist[:midpoint],item)
                  else:
                    return binarySearch(alist[midpoint+1:],item)
            testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
           print(binarySearch(testlist, 3))
           print(binarySearch(testlist, 13))
    

    【讨论】:

    • 链接断开;顺便说一句,使用切片 +1 :)
    • 究竟比OP的第一个sn-p好多少?我觉得它比您的三个选项中的任何一个都干净
    【解决方案4】:

    随机分割搜索。

    1. 当前节点 = 根。
    2. 在未找到时重复。
      • 如果当前节点 = 所需值,则已找到。
      • 如果所需的整数小于根,则从 0 到索引(根)随机选择一个索引。设置当前节点 = 选取的索引。
      • 否则,从根到 n-1 随机选择一个索引。设置当前节点 = 选取的索引。

    【讨论】:

    • 在最坏的情况下它可以在 O (n) 中工作,这不是一个二分搜索,但是谢谢!这是一种有趣的方法。
    • 我们还在切,所以它仍然是二进制的。唯一的变化是,我们不是在二分搜索中去下一个孩子,而是从当前节点的所有世代中随机选择一个孩子。所以最坏的情况仍然是 log(n)。对于大型数据集,随机化已被证明是一种有效的优化技术,因此采用了这种方法。
    【解决方案5】:

    函数式编程意味着多个函数,每个函数都有自己的单一用途,对于给定的输入返回相同的输出:

    def chopSearch(array, value):
        while len(array) != 1:
            if value == getMiddle(array):
                return value
            else:
                array = getNewArray(array, lessThan(array, value))
        return if array[0] == value value else -1
    
    def getMiddle(array):
        return if (len(array) % 2 == 0) array[len(array)/2] else array[(len(array)+1)/2]
    
    def lessThan(array, value):
        return if getMiddle(array) > value true else false
    
    def getNewArray(array, isLess):
        return if isLess array[0:getMiddle(array)] else array[getMiddle(array)+1:len(array)-1]
    

    作为一个 caviat,我不知道 python,所以我花了一分钟来尝试写这个。随意修复您看到的任何 pyton 错误。

    【讨论】:

      【解决方案6】:

      由 PSF 提供

      In [1]: import bisect
      
      In [2]: bisect??
      def bisect_left(a, x, lo=0, hi=None):
          """Return the index where to insert item x in list a, assuming a is sorted.
      
          The return value i is such that all e in a[:i] have e < x, and all e in
          a[i:] have e >= x.  So if x already appears in the list, a.insert(x) will
          insert just before the leftmost x already there.
      
          Optional args lo (default 0) and hi (default len(a)) bound the
          slice of a to be searched.
          """
      
          if lo < 0:
              raise ValueError('lo must be non-negative')
          if hi is None:
              hi = len(a)
          while lo < hi:
              mid = (lo+hi)//2
              if a[mid] < x: lo = mid+1
              else: hi = mid
          return lo
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-06
        • 1970-01-01
        • 2017-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多