返回列表中给定数字之前的数字

时间:2017-09-13 01:45:56

标签: python list binary-search

我正在尝试编写一个二进制搜索,它将在有序列表中的给定数字之前产生最高数字。

y = int(input("Enter a number:"))
numblist = [5, 8, 9, 10, 18, 20, 25, 28, 30, 35]

lowerval = numblist[0]
higherval = numblist[9]
number = 0

mid = (higherval + lowerval)//2

for y in numblist:
   number += 1
if mid == y:
   print(number)
   break

if mid < y:
    lowerval = mid
else:
    higherval = mid
    mid = (higherval + lowerval)//2

例如,如果我输入20,则返回的数字应为18.我老实说不知道如何拨打正确的位置。我在python非常新,所以任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:1)

考虑到你的代码,似乎存在二元搜索的概念问题。如果我们首先处理代码应该更有意义。

什么是二元搜索?

给定一个有序列表,以及您正在搜索的项目,您将列表减半并依次查看每一半。我们来看一个例子吧。给定[1, 2, 3, 4, 5, 6]并搜索5,您会看到列表[1,2,3][4,5,6]的两半。查看上半部分([1,2,3]),您会注意到最大的项目是3。鉴于列表是有序的,列表中的所有项目必须小于3。这意味着5(您正在搜索的内容)不可能位于较小的列表中。你现在看([4,5,6])。让我们把它分成两个列表[4][5,6],依此类推。

如何将二进制搜索应用于我的问题

给定一个数字列表和一个搜索词,您需要返回列表中仍然小于搜索词的最大项。

将列表分成两个相等的一半(就像你可以得到它们一样,奇数大小的列表总是不均匀的)。看看下半部分中的最小项目。如果最小项目大于搜索项,那么您知道您要查找的值位于前半部分列表中。否则,它在下半部分列表中。继续拆分列表,直到找到所需内容。

代码是什么样的

def largest_item_less_than_x(x, list_of_vals):
    size = len(list_of_vals)

    if (size == 0):
        return None

    if (size == 1):
        if (list_of_vals[1] < x):
            return list_of_vals[1]
        else:
            return None
    else:
        mid = size // 2
        left_half_list = list_of_vals[0:mid]
        right_half_list = list_of_vals[mid:]

        if (right_half_list[0] < x):
            return largest_item_less_than_x(x, right_half_list)
        else:
            return largest_item_less_than_x(x, left_half_list)

让我们一起浏览代码。如果给它一个空列表,则返回None。也就是说,如果没有可供选择的元素,搜索项目不会返回任何内容。

如果你给它一个值大于你要搜索的值的列表,它会返回None,即给定[6]并搜索3,你将无法找到你在寻找什么。

如果您为其指定一个值小于您要搜索的值的列表,则会返回该值。

如果你给它一个包含多个项目的列表,那么它会将列表分成两半并递归搜索每一半。

希望这是有道理的。

答案 1 :(得分:0)

以下代码片段可以执行您想要的操作,但方式相对笨拙(但更容易理解):

# Ask the user for an input
y = int(input("Enter a number: "))
# List of numbers to be searched
numblist = [5, 8, 9, 10, 18, 20, 25, 28, 30, 35]

# Set the lower bound of the search
lowerval = numblist[0]
# Set the upper bound of the search
higherval = numblist[-1]


# Search Algorithm
while True:
    mid = (lowerval + higherval) // 2
    if mid == y:
        # Here, I am assuming that you will only test against a list with only unique values.
        # It first indexes the value that was found, then subtracts one from it to obtain the value prior to the found value.
        print(numblist[numblist.index(y) - 1])
        # Then it exits the while loop.
        break
    if mid < y:
        lowerval = mid
    if mid > y:
        higherval = mid

希望这有帮助!

答案 2 :(得分:0)

此代码可以让您按照自己的要求进行操作,但我不确定用户是否需要输入列表中的数字。

def bin_search(arr,low,high,elem):
    mid = (low + high)//2
    if low <= high:
        # found element or hit end of list
        if mid == 0 or mid == len(arr) -1 or arr[mid] < elem and arr[mid+1] >= elem:
            print(arr[mid])
            return
        if arr[mid] < elem:
            bin_search(arr,mid+1,high,elem)
        else:
            bin_search(arr,low,mid-1,elem)



y = int(input("Enter a number: "))
numblist = [5, 8, 9, 10, 18, 20, 25, 28, 30, 35]

lowerval = numblist[0]
higherval = numblist[-1]

# special cases 

# highest value is smaller
if higherval < y:
    print(higherval)
# no such value is larger
elif lowerval > y:
    print("-1")
else:
    bin_search(numblist,0,len(numblist)-1,y)

答案 3 :(得分:0)

您的代码存在一些问题。首先,您将覆盖for循环语句中的输入变量y。其次,代码没有在for循环中正确缩进(可能只是你帖子中的错误?)。

获取二进制搜索的一些提示:

  1. 尝试从列表中numblist开始。检查数字是否相等,大于或小于并相应地继续。
  2. 使用中间索引而不是找到最高值和最低值之间的中间值。通过这种方式,您实际上每次都会将列表分成两半。
  3. 您可能还想考虑while循环而不是for循环。只是一个建议。
  4. 是否可以安全地假设列表将始终按照您的示例进行排序?如果不是,您可能需要添加对列表进行排序的步骤。
  5. 这是一个简单的代码,概述了我的建议并且似乎有效。可能不是最终答案,但应该有所帮助。

    y = int(input("Enter a number:"))
    numblist = [5, 8, 9, 10, 18, 20, 25, 28, 30, 35]
    
    found = False
    while not found:
        print numblist
        mid = len(numblist)/2  # integer div in python 2
        if (y == numblist[mid]):
            found = True
            x = numblist[mid - 1]
        elif len(numblist) == 1:
            found = True
            x = numblist[0]
        elif y < numblist[mid]:
            # search in the lower half
            numblist = numblist[0:mid]
        else:
            # Search in the upper half
            numblist = numblist[mid:]
    
    print x
    

答案 4 :(得分:0)

有一个问题,您的列表是否真的按升序排列?无论我认为你能做到什么,

y = int(input("Enter a number:"))
numblist = [5, 8, 9, 10, 18, 20, 25, 28, 30, 35]
tempNum = 0
index = 0
tempIndex = 0
for nums in numblist:
   tempIndex++
   if nums != y:
      if nums > tempNum:
         tempNum = nums
         index = tempIndex
   else:
      break
print(tempNum)
print(numblist[index])

所以这会循环你的numblist的每个索引。然后它会询问当前事件是否等于您输入的数字。如果是,它退出循环,如果不是,则它比较先前和当前发生的数量。找到您在列表中输入的数字后,它会退出循环。在最后一个语句中,您可以打印在发生事件发生之前包含最大数字的tempNum,或者在其列表中索引最大数字的numblist。希望你能理解我的英语。

答案 5 :(得分:0)

这是一个二元搜索的递归算法,用于在// Test cases [ '1', '12', '123', '1234', '12345', '123456', '1234567', '12345678', '123456789', '1234567890', '1.23', '1.234', '1.2345', '1.234567890', '1234567890.1234567890', '1+2-3+4', '12+34-56+78', '123+456-789', '1234+5678', '12345-678', '1234567-8', '-123456.7890', '1+2-3456.7890', '1+2-3456.7890+123456789-0.1234' ].forEach(function(str) { var out = str.replace(/(?:^|[^\.\d])\d+/g, function(match) { return match.replace(/(\d)(?=(\d\d\d)+$)/g, '$1,'); }); console.log(out); });中查找小于 x的元素的索引:

arr

请注意,如果该值小于列表

中的第一个值,则会返回def binary_search_lessthan(x, arr, offset=0): arr = sorted(arr) ix = len(arr)//2 if x==arr[ix]: return ix+offset-1 elif x<arr[ix]: if len(arr)==1: return offset-1 return binary_search_previous(x, arr[:ix], offset) elif x>arr[ix]: if len(arr)==1: return offset return binary_search_previous(x, arr[ix:], offset+ix)
-1