通过减少迭代次数来改进代码

时间:2018-10-31 11:12:02

标签: python python-3.x algorithm

我做过一项很好的运动,但我正在寻求改进。

在我的代码中,我使用的是嵌套循环,我想使其成为1循环,但我无法达到目标。

def main(l1):
    newlist = []
    numbers= max(l1) + 1
    for i in range(0,numbers):
        counter = 0
        for number in l1:
            if number >= i:
                counter += 1
        newlist.append(counter)
    print(newlist)

l1=[1,5,4,3,7,8,9]
main(l1)

它返回[7, 7, 6, 6, 5, 4, 3, 3, 2, 1] 10个索引(最大值为l1 +1)

练习的目标是找到l1中的最大值,然后测试范围(0,maximumnumber + 1)内的每个数字,

将l1中的每个数字与范围内的数字进行比较(if(number> =范围内的数字)),并计算l1中的数字大于等于范围数的次数。

我希望它有些清晰,通过代码可以更清楚

2 个答案:

答案 0 :(得分:2)

这是一个非常简单的改进:

from itertools import accumulate
def one(l1):
    counts = [0] * (max(l1) + 1)
    for n in l1:
        counts[-n - 1] += 1
    return list(accumulate(counts))[::-1]

此版本要复杂得多,但是只需两步就可以完成所有操作,我认为这是解决此问题的最低要求:

def two(l1):
    counts = []
    for n in l1:
        try:
            counts[n] += 1
        except IndexError:
            counts.extend([0] * (n - len(counts)) + [1])

    total = counts[-1]
    for i in range(-2, -len(counts) - 1, -1):
        total += counts[i]
        counts[i] = total

    return counts

两个解分别为O(n)和摊销O(n)。

您可以通过预分配列表将第二个解决方案修改为O(n),但这将需要在列表上进行三遍传递。


以上两种解决方案的基本思想是,您首先执行counting sort,然后从列表的后面开始执行running sum

答案 1 :(得分:1)

您可以通过使用sort(如评论中的@soon)来缩短时间。

对输入列表进行排序,然后仅循环显示所有数字并检查当前位置。

考虑以下代码:

def improvedTime(l):
    l.sort() # this take O(nlogn) when n in the length of l
    cnt = 0
    ans = []
    for i in range(0, l[-1]+1): # last index in the ordered list is the max element
        while (i > l[cnt] and cnt < len(l)): #until you reach bigger element
            cnt = cnt + 1
        ans.append(len(l) - cnt)
    print(ans)

l1 = [1,5,4,3,7,8,9]
l2 = [2,9,7,5,3,8,7]
improvedTime(l1)
improvedTime(l2)

输出为:

[7, 7, 6, 6, 5, 4, 3, 3, 2, 1]
[7, 7, 7, 6, 5, 5, 4, 4, 2, 1]

n是列表大小而m是max元素时,复杂度是O(max(n + m,nlogn)。

请注意,无论如何,您还必须循环到max元素-当输入[3,7,150000]时,情况可能更糟->您也可以改善这一点,但我的回答应该可以解决您的情况。

这是@LieRyan建议的方式:(我将逐步解释)

def a(l):
    ansSize = max(l) +1 # calculate the size of the output array 
    ans = [0] * (ansSize) # init the output array with zeros
    for i in l:
        ans[i] += 1 # count and mark every element from the input array and add to ans array
                    # according our example here ans = [0, 0, 1, 1, 0, 1, 0, 2, 1, 1]
    total = 0 # reset var to calculate accumulate sum
    for i in range(-1, -ansSize -1, -1): #loop the output array from the end to start
        total += ans[i] # save new total by adding all previous with current element (accumulate sum)
        ans[i] = total # set current i-index-position with total

    print(ans) # out put is: [7, 7, 7, 6, 5, 5, 4, 4, 2, 1]

l2 = [2,9,7,5,3,8,7]
a(l2)