正确实施确定清单中的位置

时间:2012-03-04 18:33:10

标签: python algorithm implementation binary-search

我有一个最喜欢的电影列表,我想根据我的喜好从最好的电影(最多点)到最糟糕的电影(只有1分)进行排序。

让我们说这个列表已包含300个已分类的电影,您想要确定新电影的分数。您可以将新电影与排序列表中的每部电影进行比较,也可以利用列表排序的知识。

我尝试将其实现为二进制搜索,因此每个插件(新电影)都具有对数复杂度。 二进制搜索实现对我来说很容易:

def binSearch(lst, number):
  left = 0
  right = len(lst) - 1
  while left <= right:
    middle = left + ((right - left) / 2)
    if number == lst[middle]:
      return True
    else:
      if number < lst[middle]:
        right = middle - 1
      else:
        left = middle + 1
  return False

但确定点对我来说非常困难。我已经调试了几个小时,但仍然会出现一些错误。我多次更改了实现,但没有任何帮助。 这是我的最后一个解决方案(也许算法处于更糟糕的状态,然后是在开始时)

def determinePoints(lst, new):
  # lst is a list of tuples with movies
  # new is a tuple with new movie (has no point associated yet)
  if not lst: # no movie has points so far
    return 1 #  now exists only one movie with associated points
  newTitle = new[0]
  newGenre = new[1]
  atMost = len(lst)
  atLeast = 0
  while atLeast < atMost - 1: # algorithm doesn't work
                              # if only two movies have associated points
    center = twoPointsCenter(atLeast, atMost)
    (title, genre) = lst[center]
    os.system("clear")
    competitionStrings = [ newTitle, newGenre, "\n" * 10, title, genre ]
    print "\n".join([ x.center(150) for x in competitionStrings ])
    c = getch()
    if c == "j": # new movie is worse than this
      atMost =  center - 1
      if atMost <= 1:
        return 1
    else: # new movie is better than this
      atLeast = center + 1
      if atLeast >= len(lst):
        return max(atLeast, 1)
  return max(twoPointsCenter(atLeast, atMost), 1)

def twoPointsCenter(left, right):
  return left + ((right - left) / 2)

你能否纠正我的解决方案(或更好地实施)以收敛并以正确的结果结束?

它应该使用0,1,2,......等长度的lst。它不应该返回小于1的值。在电影列表中不应该有两个具有相同点数的电影

当函数determinePoints返回点数时,我将为此电影更新数据库,并为每部电影增加1,其中&gt; =点数比此新电影更多。

谢谢

1 个答案:

答案 0 :(得分:1)

我认为您需要更好地查看边界索引。 len(lst)比最大索引大一个,例如:列表从0开始。我冒昧地使用0作为最低分数;这将直接为您提供lst.insert的位置。此外,我无法抗拒,并使其更像PEP 8。

你不需要所有的角落案件;我认为他们工作正常。

def determine_points(lst, new):
  # lst is a list of tuples with movies, ranked by how good the movie is
  # new is a tuple with new movie
  # the new movies position is to be determined

  new_title, new_genre = new
  at_most = len(lst)
  at_least = 0
  while at_least < at_most:
    center = (at_least + at_most) // 2
    title, genre = lst[center]
    os.system("clear")
    competition_strings = [new_title, new_genre, "\n" * 10, title, genre]
    print("\n".join(x.center(150) for x in competition_strings))
    c = getch()
    if c == "j": # new movie is worse than this
      at_most = center
    else: # new movie is better than this
      at_least = center + 1
  return at_least

修改:我使用以下代码进行了测试。

lst = []
news = [(str(i), str(i)) for i in range(10)]
import random
random.shuffle(news)
for new in news:
    print(lst)
    lst.insert(determine_points(lst, new), new)
print(lst)