I've achived these two things.

  1. Find all possible sublists of a list in given range (i ,j).

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

    Then, Possible sublists of the list "A" in the given range (2,4) is :

    [66], [66,77], [66,77,88], [77], [77,88], [88]
    
  2. And, minimum of the resultant product after multipying all the elements of the sublists:

    So, the resultant list after multiplying all the elements in the above sublists will become

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

    Now, the minimum of the above list, which is min(X) i.e 66

My Code:

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)

My Question:

This code is taking more time to get executed for the Larger Lists and Larger Ranges !
Is there any possible "Pythonic" way of reducing the time complexity of the above code ?

Thanks in advance !

EDIT :

Got it. But, If there is more than one such possible sublist with the same minimum product,

  1. I need the longest sub list range (i,j)
  2. If there are still more than one sublists with the same "longest sub range", I need to print the sub-interval which has the lowest start index.


Consider this list A = [2, 22, 10, 12, 2] if (i,j) = (0,4).
There is a tie. Min product = 2 with two possibilities '(0,0)' and '(4,4)' .
Both sub list range = 0 [ (0-0) and (4-4) ]
In this case i need to print (minproduct, [sublist-range]) = 2, [0,0]

Tried using dictionaries, It works for some inputs but not for all ! How to do this 'efficiently' ?
Thank you !

6

There are 6 answers

3
Yu Hao On BEST ANSWER

First, given the list and the index range, we can get the sublist A[i : j + 1]

[66, 77, 88]

For positive integers a and b, a * b is no less than a or b. So you don't need to do multiplying, it's not possible that multiplying of two or more elements has a smaller result. The minimum of this list is the minimum of all the multiplying results.

So the result is:

min(A[i : j + 1])
0
Emilio M Bumachar On

Take a look a itertools.combinations()

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

Call it passing the sublist, in a loop, with the other parameter varying from 1 to the length of the sublist.

It will definitely take "more time to get executed for the Larger Lists and Larger Ranges", i think that's inevitable. But might be much faster than your approach. Measure and see.

1
fferri On

For generating the sublists, it is as simple as two nested for loops in a list comprehension:

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

example:

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

For finding the minimum product:

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

(you import prod from numpy, or define it as def prod(x): return reduce(lambda i,j:i*j,x))

0
Rahul Gupta On

#EDIT: Quick Solution:

min(A[i:j+1])

Since all the numbers are positive integers, and you want to find the minimum product of all possible sublists of A[i:j+1] list
slice, it will also contain sublists of length 1. The minimum products of all such sublists will be lowest number among the A[i:j+1] slice.

Another Solution:

The below method will be useful when you need to find the maximum product of sublists or you need all the possible combinations of A[i:j+1] list slice.

We'll use itertools.combinations to solve this. We can do this in 3 steps.

Step1: Get the slice of the list

my_list = A[i:j+1]

This will give us the slice to work on.

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

Step-2 Generate all possible combinations:

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

So, we will use this to generate subsequences of length 1 to length equal to length of my_list. We will get a list of tuples with each element being a subsequence.

Step-3 : Find min product of all possible combinations

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

After getting the subsequences, we apply list comprehension along with reduce() to get the list of products for all the subsequences in my_combinations list. Then we apply min() function to get the minimum product out of the products_list which will give us our answer.

0
Padraic Cunningham On

The accepted answer is correct for all positive ints as you cannot multiply the smallest element by any number and get a smaller result. It might make more sense if you were getting all the slices greater than length 1.

If you were going to calculate it then you could use itertools.islice to get each slice and get the min using a generator expression:

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

If for i = 0 and j = 4 you considered (44, 55, 66, 88) a legitimate slice then you would need to use itertools.combinations.

0
Ankan Roy On
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])

[[], [10], [10, 20], [20], [10, 30], [20, 30], [30], [10, 20, 30]]