关于python:高效&

Efficient & Pythonic way of finding all possible sublists of a list in given range and the minimum product after multipying all elements in them?

我完成了这两件事。

  • 查找给定范围(i ,j)中列表的所有可能子列表。

    1
    2
    A = [ 44, 55, 66, 77, 88, 99, 11, 22, 33 ]
    Let, i = 2 and j = 4

    那么,给定范围内"A"列表的可能子列表(2,4)是:

    1
    [66], [66,77], [66,77,88], [77], [77,88], [88]
  • 并且,在将子列表的所有元素多重化之后,生成的产品的最小值为:因此,将上述子列表中的所有元素相乘后的结果列表将变成

    1
    X = [66, 5082, 447216, 77, 6776, 88]`

    现在,上述列表中的最小值是min(X),即66

  • 我的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    i, j = 2, 4
    A = [ 44, 55, 66, 77, 88, 99, 11, 22, 33 ]
    O, P = i, i
    mini = A[O]
    while O <= j and P <= j:
        if O == P:
            mini = min(mini, reduce(lambda x, y: x * y, [A[O]]))
        else:
            mini = min(mini, reduce(lambda x, y: x * y, A[O:P + 1]))
        P += 1
        if P > j:
            O += 1
            P = O
    print(mini)

    我的问题:

    对于较大的列表和较大的范围,执行此代码需要更多的时间!是否有任何可能的"Python式"方法来降低上述代码的时间复杂性?事先谢谢!

    编辑:

    知道了。但是,如果有多个子列表具有相同的最小产品,

  • 我需要最长的子列表范围(i,j)
  • 如果仍然有多个子列表具有相同的"最长子范围",我需要打印具有最低起始索引的子间隔。
  • 如果是(i,j) = (0,4),考虑这个列表A = [2, 22, 10, 12, 2]。有一条领带。Min product = 2有两种可能:'(0,0)' and '(4,4)'。两个子列表范围=0 [ (0-0) and (4-4) ]。在这种情况下,我需要print (minproduct, [sublist-range])=2, [0,0]

    尝试使用字典,它适用于某些输入,但不适用于所有输入!如何"有效地"做到这一点?谢谢您!


    首先,给定列表和索引范围,就可以得到子列表A[i : j + 1]

    1
    [66, 77, 88]

    对于正整数aba * b不小于ab。所以你不需要做乘法运算,两个或更多元素的乘法不可能有更小的结果。此列表的最小值是所有乘法结果的最小值。

    结果是:

    1
    min(A[i : j + 1])


    对于生成子列表,它与列表理解中的两个嵌套for循环一样简单:

    1
    2
    def sublists(l,i,j):
        return [l[m:n+1] for m in range(i,j+1) for n in range(m,j+1)]

    例子:

    1
    2
    >>> sublists(A,2,4)
    [[66], [66, 77], [66, 77, 88], [77], [77, 88], [88]]

    求最小积:

    1
    2
    >>> min(map(prod, sublists(A,2,4)))
    66

    (您从numpy导入prod或定义为def prod(x): return reduce(lambda i,j:i*j,x))


    接受的答案对于所有的正整数都是正确的,因为你不能用最小的元素乘以任何数字,得到的结果也会更小。如果所有切片的长度都大于1,这可能更有意义。

    如果要计算它,那么可以使用itertools.islice获取每个切片,并使用生成器表达式获取最小值:

    1
    2
    3
    4
    5
    6
    7
    from itertools import islice
    from operator import mul

    print(min(reduce(mul, islice(A, n, k + 1), 1)
              for n in range(i, j + 1) for k in range(n, j + 1)))

    66

    如果对于i=0和j=4,您认为(44, 55, 66, 88)是一个合法的切片,那么您需要使用itertools.combinations。


    #编辑:快速解决方案:

    1
    min(A[i:j+1])

    因为所有的数字都是正整数,所以您需要找到A[i:j+1]列表所有可能子列表的最小积。切片,它还将包含长度为1的子列表。所有这些子列表的最小积将是A[i:j+1]片中的最小数。

    另一个解决方案:

    当您需要找到子列表的最大乘积或需要A[i:j+1]列表切片的所有可能组合时,下面的方法将非常有用。

    我们将使用itertools.combinations来解决这个问题。我们可以分三步完成。

    步骤1:获取列表切片

    1
    my_list = A[i:j+1]

    这将给我们一个工作机会。

    1
    2
    3
    my_list = A[2:5]
    my_list
    [66, 77, 88]

    步骤2生成所有可能的组合:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import itertools

    my_combinations = []

    for x in range(1, len(my_list)+1):
        my_combinations.extend(list(itertools.combinations(my_list,x)))

    my_combinations
    [(66,), (77,), (88,), (66, 77), (66, 88), (77, 88), (66, 77, 88)]

    iterools.combinations returns r length subsequences of elements from
    the input iterable

    因此,我们将使用它生成长度为1到长度等于my_list的子序列。我们将得到一个元组列表,其中每个元素都是一个子序列。

    步骤3:找到所有可能组合的最小积

    1
    2
    3
    4
    5
    products_list = [reduce(lambda i,j:i*j, x) for x in my_combinations]
    [66, 77, 88, 5082, 5808, 6776, 447216]

    min(products_list)
    66

    在得到子序列后,我们将列表理解与reduce()一起得到my_combinations列表中所有子序列的产品列表。然后我们应用min()函数,得到products_list的最小积,给出我们的答案。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def solution(a_list):

        sub = [[]]

        for i in range(len(a_list)):
            for j in range(len(a_list)):
                if(i == j):
                    sub.append([a_list[i]])
                elif(i > j):
                    sub.append([a_list[j],a_list[i]])
        sub.append(a_list)
        return sub


    solution([10, 20, 30])
    1
    [[], [10], [10, 20], [20], [10, 30], [20, 30], [30], [10, 20, 30]]

    看一看itertools.combinations()

    https://docs.python.org/3/library/itertools.html itertools.combinations.

    在循环中调用它传递子列表,其他参数从1到子列表的长度不等。

    我认为这肯定需要"为更大的列表和更大的范围执行更多的时间",这是不可避免的。但可能比你的方法快得多。测量并查看。