我在Python中找不到以下功能时遇到了问题:
给定一组数字,如果不存在这样的数字,则返回小于或等于
n
的最大数字或返回None
。
例如,给定列表[1, 3, 7, 10]
和n = 9
,函数将返回7.
我正在寻找类似于Java's TreeSet.lower
的Python功能。
我可以使用其他数据结构。堆似乎合适。
O(n)解决方案对于问题的规模来说太慢了。我正在寻找一个O(log n)解决方案。
我正在https://www.hackerrank.com/challenges/maximise-sum工作。可能的值范围为1 - 10 ^ 14,因此使用带二进制搜索的排序列表太慢。
我目前的想法是直接迭代Python's heapq backing array。我希望可能会有更多的Pythonic。
答案 0 :(得分:3)
我认为您可以使用 bintrees 库:https://bitbucket.org/mozman/bintrees/src
示例:
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)
答案 1 :(得分:2)
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
我从similar question获取上述解决方案。
答案 2 :(得分:1)
如果你不能对数组的排序做出任何假设,那么我认为你能做的最好是O(n):
def largest_less_than(numlist, n):
answer = min(numlist, key=lambda x: n-x if n>=x else float('inf'))
if answer > n:
answer = None
return answer
如果问题是重复获取同一数据集中不同n
值的最大值,则可能有一个解决方案是使用bucket sort将列表排序为O(n) ,然后重复使用bisect
。
答案 3 :(得分:0)
您可以使用selection algorithm。下面我为此提供了一个简单的算法:
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'
答案 4 :(得分:0)
如果您不必支持列表中的动态添加和删除,那么只需对其进行排序并使用二进制搜索来查找最大的&lt; n在O(log N)时间内。
答案 5 :(得分:0)
ig-melnyk的回答可能是完成这个问题的正确方法。但是由于HackerRank没有办法使用库,这里是我用来解决这个问题的Left-Leaning Red Black Tree的实现。
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
答案 6 :(得分:0)
您可以减少要查找的号码,直到找到为止。
此功能将找到fs中最大数<= n的位置,即整数排序列表。
如果没有小于或等于n的数字,则返回-1。
def findmaxpos(n):
if n < fs[0]: return -1
while True:
if n in fs: return fs.index(n)
n-=1