Python—获取堆中小于n的最大数

Python—获取堆中小于n的最大数,python,algorithm,heap,dynamic-programming,Python,Algorithm,Heap,Dynamic Programming,在Python中查找以下功能时遇到问题: 给定一组数字,返回小于或等于n的最大数字,如果不存在此类数字,则返回None 例如,给定列表[1,3,7,10]和n=9,函数将返回7 我正在寻找类似的Python功能 我可以使用另一种数据结构。堆似乎是合适的 O(n)解对于问题的规模来说太慢了。我正在寻找一个O(logn)解决方案 背景 我正在工作。可能的值范围为1-10^14,因此使用带二进制搜索的排序列表速度太慢 我目前的想法是直接迭代。我希望可能会有更具python风格的东西。如果你不能对数组的

在Python中查找以下功能时遇到问题:

给定一组数字,返回小于或等于
n
的最大数字,如果不存在此类数字,则返回
None

例如,给定列表
[1,3,7,10]
n=9
,函数将返回7

我正在寻找类似的Python功能

我可以使用另一种数据结构。堆似乎是合适的

O(n)解对于问题的规模来说太慢了。我正在寻找一个O(logn)解决方案

背景 我正在工作。可能的值范围为1-10^14,因此使用带二进制搜索的排序列表速度太慢


我目前的想法是直接迭代。我希望可能会有更具python风格的东西。

如果你不能对数组的顺序做出任何假设,那么我认为你能做的最好的事情就是O(n):

如果问题是重复获取同一数据集上不同
n
值的最大值小于,那么可能有一种解决方案用于将列表按O(n)排序,然后重复使用

nextLowest  = lambda seq,x: min([(x-i,i) for i in seq if x>=i] or [(0,None)])
用法:

t = [10, 20, 50, 200, 100, 300, 250, 150]
print nextLowest(t,55)
> 50
我从a中获取上述解决方案。

您可以使用。下面我提供了一个简单的算法:

numbers = [1, 3, 7, 10]
n = 9
largest_number = None
for number in numbers:    
    if number<=n:
        largest_number=number
    else:
        break

if largest_number:
    print 'value found ' + str(largest_number)
else:
    print 'value not found'
number=[1,3,7,10]
n=9
最大数量=无
对于数字中的数字:

如果数字我认为您可以使用bintrees库来实现这一点:

示例:

tree = bintrees.RBTree()
In [10]: tree.insert(5,1) 
In [11]: tree.insert(6,1) 
In [12]: tree.insert(10,1)
tree.ceiling_item(5)  -> (5,1)

这个操作的复杂性是O(logN)

如果您不必支持从列表中动态添加和删除,那么只需对其进行排序并使用二进制搜索来查找O(logN)时间内最大的ig melnyk的答案可能是完成这个问题的正确方法。但是由于HackerRank没有一种使用库的方法,下面是我用来解决这个问题的一个实现

class LLRB(object):

    class Node(object):
        RED = True
        BLACK = False

        __slots__ = ['value', 'left', 'right', 'color']

        def __init__(self, value):
            self.value = value
            self.left = None
            self.right = None
            self.color = LLRB.Node.RED


        def flip_colors(self):
            self.color = not self.color
            self.left.color = not self.left.color
            self.right.color = not self.right.color


    def __init__(self):
        self.root = None


    def search_higher(self, value):
        """Return the smallest item greater than or equal to value.  If no such value
        can be found, return 0.

        """
        x = self.root
        best = None
        while x is not None:
            if x.value == value:
                return value
            elif x.value < value:
                x = x.left
            else:
                best = x.value if best is None else min(best, x.value)
                x = x.right

        return 0 if best is None else best

    @staticmethod
    def is_red(node):
        if node is None:
            return False
        else:
            return node.color == LLRB.Node.RED


    def insert(self, value):
        self.root = LLRB.insert_at(self.root, value)
        self.root.color = LLRB.Node.BLACK


    @staticmethod
    def insert_at(node, value):
        if node is None:
            return LLRB.Node(value)

        if LLRB.is_red(node.left) and LLRB.is_red(node.right):
            node.flip_colors()

        if node.value == value:
            node.value = value
        elif node.value < value:
            node.left = LLRB.insert_at(node.left, value)
        else:
            node.right = LLRB.insert_at(node.right, value)


        if LLRB.is_red(node.right) and not LLRB.is_red(node.left):
            node = LLRB.rotate_left(node)
        if LLRB.is_red(node.left) and LLRB.is_red(node.left.left):
            node = LLRB.rotate_right(node)

        return node
类LLRB(对象):
类节点(对象):
红色=真
黑色=假
__插槽\=['value','left','right','color']
定义初始值(自身,值):
自我价值=价值
self.left=无
self.right=无
self.color=LLRB.Node.RED
def翻转_颜色(自身):
self.color=非self.color
self.left.color=非self.left.color
self.right.color=非self.right.color
定义初始化(自):
self.root=None
def搜索_更高(自身,值):
“”“返回大于或等于值的最小项。如果没有此值
无法找到,返回0。
"""
x=自根
最佳=无
虽然x不是无:
如果x.value==值:
返回值
elif x.value<值:
x=x左
其他:
最佳值=x.value,如果最佳值不是其他最小值(最佳值,x.value)
x=x。对
如果最佳值不是其他最佳值,则返回0
@静力学方法
def为红色(节点):
如果节点为无:
返回错误
其他:
返回node.color==LLRB.node.RED
def插入(自身,值):
self.root=LLRB.insert_at(self.root,value)
self.root.color=LLRB.Node.BLACK
@静力学方法
def insert_位于(节点,值):
如果节点为无:
返回LLRB.Node(值)
如果LLRB.is_red(node.left)和LLRB.is_red(node.right):
node.flip_colors()
如果node.value==值:
node.value=值
elif node.value<值:
node.left=LLRB.insert_at(node.left,value)
其他:
node.right=LLRB.insert_at(node.right,value)
如果LLRB.is_red(node.right)而不是LLRB.is_red(node.left):
node=LLRB.向左旋转(node)
如果LLRB.is_red(node.left)和LLRB.is_red(node.left.left):
node=LLRB.向右旋转(node)
返回节点

您可以减少正在查找的号码,直到找到为止


这个函数将找到最大数的位置是的,有几个很好的库供我使用。不幸的是,我不能使用HackerRank上的库。问题是你需要支持重复搜索相同的数据吗?对于单个搜索,将无序列表转换为另一个数据结构几乎肯定已经是O(n)了。是的,这个问题是一个扭曲的最大子序列问题。因此,对于
n
元素,我需要使用上面描述的
lookup
。因此,我确实需要
查找
来花费O(logn)时间来支持O(nlogn)的总体复杂性
t=xrange(110000000)下一次打印(t,10000000-1)
在我的机器上需要3.6秒。我已经做了一些计时
n=10000000-1 number=xrange(110000000)
在我的机器上花费2.3秒。我已经做了一些计时<代码>n=10000000-1 num_list=xrange(110000000)
在我的机器上需要2.1秒。
class LLRB(object):

    class Node(object):
        RED = True
        BLACK = False

        __slots__ = ['value', 'left', 'right', 'color']

        def __init__(self, value):
            self.value = value
            self.left = None
            self.right = None
            self.color = LLRB.Node.RED


        def flip_colors(self):
            self.color = not self.color
            self.left.color = not self.left.color
            self.right.color = not self.right.color


    def __init__(self):
        self.root = None


    def search_higher(self, value):
        """Return the smallest item greater than or equal to value.  If no such value
        can be found, return 0.

        """
        x = self.root
        best = None
        while x is not None:
            if x.value == value:
                return value
            elif x.value < value:
                x = x.left
            else:
                best = x.value if best is None else min(best, x.value)
                x = x.right

        return 0 if best is None else best

    @staticmethod
    def is_red(node):
        if node is None:
            return False
        else:
            return node.color == LLRB.Node.RED


    def insert(self, value):
        self.root = LLRB.insert_at(self.root, value)
        self.root.color = LLRB.Node.BLACK


    @staticmethod
    def insert_at(node, value):
        if node is None:
            return LLRB.Node(value)

        if LLRB.is_red(node.left) and LLRB.is_red(node.right):
            node.flip_colors()

        if node.value == value:
            node.value = value
        elif node.value < value:
            node.left = LLRB.insert_at(node.left, value)
        else:
            node.right = LLRB.insert_at(node.right, value)


        if LLRB.is_red(node.right) and not LLRB.is_red(node.left):
            node = LLRB.rotate_left(node)
        if LLRB.is_red(node.left) and LLRB.is_red(node.left.left):
            node = LLRB.rotate_right(node)

        return node
def findmaxpos(n):
  if n < fs[0]: return -1  
  while True:
    if n in fs: return fs.index(n)
    n-=1