在`Python 3`中,从整数列表中获取最多m个元素和最后m个元素

时间:2018-03-06 12:55:54

标签: python-3.x

Python 3中,如何有效地从整数列表中获取最多m个元素和最后m个元素n次(省略先前的最大值)?

arr=[10,20,35,30,10,45,0,20,25,50,15]
m=4
n=3
1<=array size<=10^5
0<=array element<=10^9
1<=n<=array size
1<=m<=array size

First m elements = [10,20,35,30]
Last m elements = [20,25,50,15]

0th element of the output list --> maximum of above i.e. 50

after omitting 50
arr=[10,20,35,30,10,45,0,20,25,15]
First m elements = [10,20,35,30]
Last m elements = [0,20,25,15]
1th element of the output list --> maximum of above i.e. 35

and so on... upto (n-1)th element

我尝试使用基本逻辑,并且它对小输入工作正常,但是因为列表大小得到超时错误,m,n可以高达10 ^ 5。是否有任何python特定的快捷方式来有效地实现它?

代码#1

for i in range(0,n):
    if len(arr)>2*m+n-i-1:
        temp=arr[:m]+arr[-m:]
    else:
        temp=arr
    x=max(temp)
    ind=temp.index(x)
    if ind>=m:
        ind=ind-len(temp)
    arr.pop(ind)
    print(x)

代码#2

l=len(arr)
for j in range(0,n):
    acnt=0
    bcnt=0
    ai=0
    bi=-1
    x=-1
    while acnt<m and ai<l:
        if arr[ai]!=-1:
            if arr[ai]>x:
                x=arr[ai]
                i=ai
            acnt=acnt+1
        ai=ai+1
    while bcnt<m and bi>=-l:
        if arr[bi]!=-1:
            if arr[bi]>x:
                x=arr[bi]
                i=bi
            bcnt=bcnt+1
        bi=bi-1
    print(x)
    arr[i]=-1

此外,我尝试使用递归和排序,但我仍然遇到大型测试用例的超时错误。还有其他解决方案复杂性较低吗?

3 个答案:

答案 0 :(得分:0)

m = 4
n = 3
arr = [10,20,35,30,10,45,0,20,25,50,15]

# From Start
for x in range(n):
    maximum = max(arr[:m])
    arr.remove(maximum);
    print(maximum)

arr = [10,20,35,30,10,45,0,20,25,50,15]

# From End
for x in range(n):
    maximum = max(arr[m+1:])
    arr.remove(maximum);
    print(maximum)

将列表切片到第m个元素并取其最大值,然后从初始列表中删除第一个匹配项。

由于它从数组中删除了最大元素并假设这些范围可能重叠,因此需要初始化初始数组两次。除非你知道它们不会重叠。

或者如果目标是从开头到结尾依次采取最大值,那么可以很容易地将其修改为:

m=4
n=3
arr=[10,20,35,30,10,45,0,20,25,50,15]

for x in range(n):
    maximum = max(arr[m+1:]) # From End
    arr.remove(maximum);
    print(maximum)
    maximum = max(arr[:m]) # From Start
    arr.remove(maximum);
    print(maximum)

显然可能有更好的解决方案。

您可以通过使用某种记忆和动态编程来加速该过程。按排序顺序跟踪子数组值,以便轻松访问下一个最大值,并且只能逐个添加/删除它们。

或创建一些自定义数据结构以跟踪本地最大值。

同时检查一下: Finding maximum in sliding window

答案 1 :(得分:0)

完整的实施可能如下所示:

import itertools

def f(array, m, n):
    l = len(array)
    if l <= 2 * m: # The full array fits in the first iteration
        temp = sorted(array)
        for i in range(-1, -min(n,l)-1, -1):
            yield temp[i]
    else:
        i = m          # Next element from the start
        j = l - m - 1  # Next element from the end
        temp = [(array[k], k) for k in itertools.chain(range(i), range(j + 1, l))]
        for _ in range(n):
            temp.sort()
            max, index = temp[-1]
            yield max
            if i > j:  # Check that we haven't crossed the indexes
                break
            if index < i:
                temp[-1] = (array[i], i)
                i += 1
            else:
                temp[-1] = (array[j], j)
                j -= 1

# Usage
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=4, n= 3)))
# [50, 35, 30]
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=4, n= 4)))
# [50, 35, 30, 45]
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=4, n=10)))
# [50, 35, 30, 45]
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=4, n=12)))
# [50, 35, 30, 45]

print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=10, n= 3)))
# [50, 45, 35]
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=10, n= 4)))
# [50, 45, 35, 30]
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=10, n=10)))
# [50, 45, 35, 30, 25, 20, 20, 15, 10, 10]
print(list(f([10, 20, 35, 30, 10, 45, 0, 20, 25, 50, 15], m=10, n=12)))
# [50, 45, 35, 30, 25, 20, 20, 15, 10, 10, 0]

答案 2 :(得分:0)

最后删除额外的循环开销,它适用于所有测试用例。谢谢你的帮助。

f=0
r=len(arr)-1
f_flag=1
r_flag=1
for i in range(0,n):
    if r<=f+2*m-1:
        arr[f:r+1]=sorted(arr[f:r+1],reverse=True)
        f=f+n-i
        break
    else:
        for j in range(0,m-1):
            if f_flag==1:
                if f+j+1<len(arr):
                    if arr[f]<arr[f+j+1]:
                        x=arr[f]
                        arr[f]=arr[f+j+1]
                        arr[f+j+1]=x
            if r_flag==1:
                if r-1-j>=0:
                    if arr[r]<arr[r-1-j]:
                        x=arr[r]
                        arr[r]=arr[r-1-j]
                        arr[r-1-j]=x
        if arr[f]>=arr[r]:
            f=f+1
            f_flag=1
            r_flag=0
        else:
            r=r-1
            f_flag=0
            r_flag=1
return(sum(arr[:f]+arr[r+1:]))