2013-03-08 50 views
1

我遇到一些麻烦的算法(如要查找最大值和最小值)比较元素,而不是算法本身,而是实现,让我解释一下:如何在列表

比方说,清单n = [0,1,1,2,3,5,8,13,-1,99]; len(n) = 10 然后globalMin, globalMax = n[0], n[0] q若要跳过1次迭代从列表

现在我要做的是通过“对”比较,所以,因为我已经使用N [0]我开始比较N [1]和n [2 ]找到这两个值之间的最大值和最小值,然后将其与y全局最小值,最大值,然后n [3]和n [4]进行比较,并将nm与我的全局值进行比较,然后n [5]和n [6] ..直到我必须比较n [9]和n [10],因为你可以看到n [10]在我的列表中不存在。我以为我可以使用下面的代码与清单切片解决这个问题:

for i in range(1, len(n), 2): 

    if n[i:i+1] > n[i+1:i+2]: 
     minl, maxl = n[i+1:i+2], n[i:i+1] # minl = local min; maxl = local max 
    else: 
     maxl, minl = n[i+1:i+2], n[i:i+1] 

但是这不会工作,如果我的最后一个元素只有一个(如上面的例子),因此,你可以猜测,如果min或max是我列表中的最后一个元素,它将被忽略。我一直在试图解决这个索引或列表切片,但没有运气,有什么建议吗?我必须以'Pythonic'的方式做到这一点,并确保尽可能简单和简短,而不使用进口。我已经计算出基于下一个图像的算法的其余部分:Image

+0

我会假设你正在做这个教育exersize,但值得注意的是,在任何真实情况下,这最好用'min(n),max(n)'来实现。 – 2013-03-08 01:05:07

+0

是的,它仅用于教育目的,这就是为什么我被要求不要使用任何外部库或函数,它只能与基本语句(如,,,elif,for等) – 2013-03-08 01:07:26

+0

'min()'和'max()'是内置函数,而不是* external *,但我明白你的意思。值得注意的是,通过索引进行迭代效率低,不灵活,难于阅读并且容易失败,应该避免。 – 2013-03-08 01:09:30

回答

3

您可以首先检查列表的长度,如果它是奇数长度,则可以在列表末尾附加最后一个元素。追加是一个O(1)操作,所以它不会影响时间复杂度。

您可以使用while循环:

In [78]: lis = [0,1,1,2,3,5,8,13,-1] 

In [79]: if len(lis)%2 !=0 : #if the list is of odd length then append the last item to it 
    lis.append(lis[-1]) 
    ....:  

In [80]: i=0 

In [81]: while i<len(lis)-1: 
    if lis[i]>lis[i+1]: 
     local_max,local_min=lis[i],lis[i+1] 
    elif lis[i]<lis[i+1]:  
     local_max,local_min=lis[i+1],lis[i] 
    else: 
     local_max,local_min=lis[i],lis[i+1] 
    print local_min,local_max 
    i+=2 
    ....:  
0 1 
1 2 
3 5 
8 13 
-1 -1 

,或者你可以使用一个迭代器:

In [86]: it=iter(lis) 

In [87]: lis = [0,1,1,2,3,5,8,13,-1] 

In [88]: if len(lis)%2 !=0 : 
    lis.append(lis[-1]) 
    ....:  

In [89]: it=iter(lis) 

In [90]: for _ in xrange(len(lis)/2): 
    ....:  a,b=next(it),next(it) 
    ....:  if a>b: 
    ....:   local_max,local_min=a,b 
    ....:  elif a<b:  
    ....:   local_max,local_min=b,a 
    ....:  else:  
    ....:   local_max,local_min=a,b 
    ....:  print local_min,local_max  
    ....:  
0 1 
1 2 
3 5 
8 13 
-1 -1 
+0

这正是我想要的!非常感谢,我不知道迭代器的存在。有这么多,我仍然不知道,非常感谢你! – 2013-03-08 01:30:41

+0

如果列表中有奇数个项目,则会发生错误。它似乎大规模地使用range()来使用'for'循环来处理迭代器。 – 2013-03-08 01:33:00

+0

@Lattyware固定的。 – 2013-03-08 01:38:20

2

我认为这是最Python化实现这一点:

from itertools import zip_longest 

n = [0, 1, 1, 2, 3, 5, 8, 13, -1, 99] 
global_min = global_max = n[0] 

groups = [iter(n)] * 2 
for a, b in zip_longest(*groups): 
    if b is not None: 
     if a > b: 
      local_min, local_max = b, a 
     else: 
      local_min, local_max = a, b 
    else: 
     local_min = local_max = a 
    if local_min < global_min: 
     global_min = local_min 
    if local_max > global_max: 
     global_max = local_max 

print(global_min, global_max) 

我们使用itertools.zip_longest()(在2.x中为itertools.izip_longest())和t他重复了同一个迭代器。然后,我们循环这个,这给了我们成对的值。然后我们进行检查,如果值是最后一个,我们将其分配为local_minlocal_max,否则,我们比较这两个值并进行适当分配。

然后,我们比较(并潜在更新)global_minglobal_max