繁体   English   中英

将列表中的每个元素与之前的所有连续元素进行比较

[英]Compare each element in a list with all the previous consecutive elements

我想将列表 a 的每个元素与其之前的连续元素进行比较。 i 在前向的每次迭代需要对 j 在后向的迭代次数(或简单地从 i 的当前索引反向迭代 j)并比较之前的连续元素是否满足条件 a[i] >= a[j] . 如果条件为真,则将计数加 1 (count++) 如果条件失败(即 a[i] < a[j] 在任何索引处)将计数附加到新列表 li[] 并打印 li。

我尝试了以下方法但失败了:

a = [1,2,3,2,4,6,1,2]
li=[]
count = 0
for i in range(len(a)):
  for j in range(i,0,-1):
    while a[i] >= a[j]:
      count+=1
    li.append(count)
    print(li)

输出应如下所示:

1 2 3 1 5 6 1 2

有没有什么具体的方法可以解决这个复杂度为 O(n) 的问题。 就像有什么算法可以解决在某种方法中需要 2 个或更多嵌套循环的问题,以优化时间复杂度。

这是来自需要堆栈在线性时间内解决的前瞻或后视问题类别:

def smaller_preceding(a):
    stack = []
    result = []
    for i, x in enumerate(a):
        while stack and a[stack[-1]] < x:
            stack.pop()
        # current index minus index of last bigger element!
        result.append(i - (stack[-1] if stack else -1))
        stack.append(i)  
    return result

>>> smaller_preceding([1,2,3,2,4,6,1,2])
[1, 2, 3, 1, 5, 6, 1, 2]

堆栈跟踪严格减少元素的索引,例如,在某一时刻它将是:

[2, 3]  
# stack contains indeces  (0 and 1 have been popped)

对应元素:

[3, 2]  
# ... of decreasing elements (... because 1 and 2 were smaller than 3)

其理由是,对于每一个元素xa ,你知道你可以完全忘记所有小先前的元素,你将永远不会“闯过” x上回头看时后(如果有更小的元素比未来元素小,所以将是x !)。

您可以轻松验证for循环是否有 n 次迭代。 此外,可以看到while循环也最多有 n 次迭代(即使它是嵌套的),因为每个索引只能从堆栈中弹出一次。 因此,整个算法在时间和空间上都是线性的。

使用 numpy 您可以评估整个np.array比较。 这为您节省了一个循环。 第一步创建包含数字大于当前值的所有索引的array([1, 2, 3, 4, 5]array([1, 2, 3, 4, 5] (对于原始列表的索引 6)。
在第二步中,将空数组作为当前索引+1 idx+1添加到li ,因为这是该点必须返回多远(直到列表开始)。 如果数组非空,则将idx与最大值(即index -array 中最右边的索引)之间的index相加。 同样,这是指针必须移动的距离。

import numpy as np

a = np.array([1, 2, 3, 2, 4, 6, 1, 2])
li = []

for idx, val in enumerate(a):
    index = np.where(a[0:idx+1] > val)
    if np.size(index) == 0:
        li.append(idx+1)
    else:
        li.append(idx - np.max(index))
    
print(li)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM